Android Thread and Handler

Thread

先来看看官方关于thread的说明,其中提到有二种方式来实现需要在线程中运行的代码。

A Thread is a concurrent unit of execution. It has its own call stack for methods being invoked, their arguments and local variables. Each application has at least one thread running when it is started, the main thread, in the main ThreadGroup. The runtime keeps its own threads in the system thread group.

There are two ways to execute code in a new thread. You can either subclass Thread and overriding its run() method, or construct a new Thread and pass a Runnable to the constructor. In either case, the start() method must be called to actually execute the new Thread.

Each Thread has an integer priority that affect how the thread is scheduled by the OS. A new thread inherits the priority of its parent. A thread’s priority can be set using the setPriority(int) method.

继承Thread类,并重写run()方法

    public class MyThread extends Thread {
        @Override
        public void run() {
            // do something...
        }
    }

    // 使用线程类
    Thread t = new MyThread();
    t.run();    // 调用run后,线程才真正跑起来

使用Runnable定义的任务

一个类实现了Runnalbe接口,我们可以认为其定义了一个任务,这个任务可以由一个线程去执行,也可以由一个计时器去驱动。

/**
 * Represents a command that can be executed. Often used to run code in a
 * different {@link Thread}.
 */
public interface Runnable {

    /**
     * Starts executing the active part of the class' code. This method is
     * called when a thread is started that has been created with a class which
     * implements {@code Runnable}.
     */
    public void run();
}

// MyTask.java
public class MyTask implements Runnable {
    private static int taskCount = 0;
    private final int taskID = taskCount++;
    protected int countDown = 10;

    public MyTask() {}

    public String status() {
        return "#" + taskID + "(" + countDown + ")";
    }

    @Override
    public void run() {
        while (countDown-- > 0) {
            Log.v("examle", status());
            Thread.yield();
        }
    }
}

// 如果要在另一个线程中启动该任务
Thread t = new Thread(new MyTask());
t.run();

二种实现方法殊途同归

以下是Thread的run()方法实现, 如果构造函数时指定了Runnable接口(保存在target变量),调用run时,直接运行target任务。
如果子类重载了run()方法,直接运行子类中run()的代码。
本质是一样的,只是提供了二种不同的形势。

public void run() {
    if (target != null) {
        target.run();
    }
}

Runnable target;

Handler

A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue. Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it – from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

Handler主要用来发送和处理消息(或者任务)。它必须与一个线程的消息队列关联起来(理解这点很重要,Handler的工作模式决定了这一点,所以一个无消息队列的工作线程是不允许实例化Handler的,必须先通过Looper创建消息队列,这个以后再讲)。消息循环时,一个一个的处理这些消息或任务。Windows通过窗口名把消息交由窗口处理程序来处理,Android通过Handler把消息交由Handler的消息处理函数来处理(handleMessage()或任务的回调函数),代码执行在与Handler相关联的线程中执行。

基于此,Handler有二个主要的功能:(1) 指定消息或任务在未来某个时间点执行,因为发送消息时可以指定时间参数,具体可参考原代码。(2) 让任务在另一个线程中去执行,比如工作线程触发的某个状态需更新UI,可以把更新UI的任务发送主线程去执行,一般不允许在工作线程更新UI(Windows也是不建议在工作线程更新UI)。

下面的示例代码创建了二个Handler,一个直接重载了handleMessage()接口, 一个是构造函数时直接传入Handler.Callback接口,二种用法的本质是一样的,有兴趣的可以看下Handler的原码的dispatchMessage()方法。此处没有调用Looper.prepare()来创建消息队列,是因为主UI线程启动时会自动创建消息队列。

向某个线程发送消息或任务,直接使用与其关联的Handler,调用相应的接口就可以了,Handler的消息处理程序会处理该消息或回调任务的执行代码(Runnable::run())。因为会进消息队列,消息处理会异步执行,也不能将处理结果直接返回。(Windows编程有PostMessage与SendMessage的区别,SendMessage可阻塞执行,直接将处理结果返回,这里就相当于PostMessage了,全部是异步执行。)

public class MainActivity extends Activity implements Handler.Callback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        Thread t1 = new MyThread();
        t1.start();

        Thread t2 = new Thread(new MyTask());
        t2.start();

    }

    public static class MyTask implements Runnable {
        private static int taskCount = 0;
        private final int taskID = taskCount++;
        protected int countDown = 10;

        public MyTask() {}

        public String status() {
            return "#" + taskID + "(" + countDown + ")";
        }

        @Override
        public void run() {
            while (countDown-- > 0) {
                Log.v("examle", status());
                Thread.yield();
            }
        }
    }

    class MyThread extends Thread {
        @Override
        public void run() {
            int count = 0;
            while(count++ < 5) {
                mMainHandler.sendEmptyMessage(count);
                mMainHandler2.sendEmptyMessage(10+count);
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        // TODO Auto-generated method stub
        Log.v("handler msg", "msg.what == " + Integer.toString(msg.what));
        return true;
    }

    public Handler mMainHandler = new Handler(this);
    public Handler mMainHandler2 = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            Log.v("handler2 msg", "msg.what == " + Integer.toString(msg.what));
        }
    };
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值