HandlerThread分析

1, 引言

一般情况下Android中新诞生的线程是没有开启消息循环的。主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。 Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。然后通过Looper.loop() 让Looper开始工作,从消息队列里取消息,处理消息。如果想在子线程开启消息循环呢?

Class mythread extends Thread{
    @Override
    public void run() {
          Looper.prepare();
           Handler Myhandler = new Handler(){
@Override
           public void handleMessage(Message msg) {
               switch (msg.what) {
                   case 2:
                       •••
                       break;
                     }
	};
Message reset = mHandler.obtainMessage();
	reset.what = 2;
           Myhandler.sendMessageDelayed(test,1000);
     Looper.loop();
}
}

注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。

说了这么多,还没有说到正题,这些和HandlerThread有什么关系呢?

2,HandlerThread 使用方法

在一个activity中, HandlerThread用法如下,

protected void onCreate(Bundle savedInstanceState) {
        •••

        //创建一个线程,线程名字:handler-thread
        myHandlerThread = new HandlerThread( "handler-thread") ;
        //开启一个线程
        myHandlerThread.start();
        //在这个线程中创建一个handler对象
        handler = new Handler( myHandlerThread.getLooper() ){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                //这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
               Log.d( "handler " , "消息: " + msg.what + "  线程: " + 
Thread.currentThread().getName()  ) ; 
            }
        };

        //在主线程给handler发送消息
        handler.sendEmptyMessage( 1 ) ;
        new Thread(new Runnable() {
            @Override
            public void run() {
             //在子线程给handler发送数据
             handler.sendEmptyMessage( 2 ) ;
            }
        }).start() ;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //释放资源
        myHandlerThread.quit() ;
    }

运行效果:

/com.app D/handler: 消息: 1  线程: handler-thread
/com.app D/handler: 消息: 2  线程: handler-thread

由此可见, HandlerThread的主要作用如下,

1,HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。

2,开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread本质是一个线程,在线程内部,代码是串行处理的。

3,但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。

4,HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。

5,对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。

3,HandlerThread 源码

HandlerThread定义如下,

public class HandlerThread extends Thread {
    int mPriority;  // 线程优先级
    int mTid = -1;
    Looper mLooper; 

HandlerThread继承于Thread,并且有自己的Looper。HandlerThread的2个构造方法如下,

public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }

3.1 start方法

Start方法是调用父类Thread的方法, 随之的run方法如下,

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper(); // 初始化mLooper对象
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

看到了吧,在该方法中调用了Looper的prepare和loop方法,并且初始化mLooper对象。几乎和android进程中的UI线程一样。

3.2 getLooper方法

构造Handler对象是,会调用HandlerThread的getLooper方法,源码如下,

public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

返回run方法中得到的mLooper对象。

4,小结

说到这里, HandlerThread的实质就是在子线程中处理消息循环。如果不用HandlerThread的话,需要向引言中的那样手动调用Looper的prepare和loop方法。


run方法里面当mLooper创建完成后有个notifyAll(),getLooper方法中有个wait(),这是为什么呢?因为mLooper在一个子线程中执行,而我们的handler是在UI线程初始化的,也就是说,必须等到mLooper创建完成,才能正确的返回getLooper();wait(),notify()就是为了解决这两个线程的同步问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值