美文网首页
HandlerThread源码分析

HandlerThread源码分析

作者: Felix_lin | 来源:发表于2018-12-01 10:42 被阅读22次

    HandlerThread作为子线程管理常用类,他自带封装的Looper处理Message,可以说是十分实用。子线程调度任务,方便我们在子线程中做更多的花样。

    介绍:

    HandlerThread内部实现很简单,主要用在需要进行子线程调度任务的时候创建,但是想要完善熟悉原理,你必须熟悉Handler的内部原理实现。请看我的文章:【Android源码篇】 最详细的AsyncTask源码剖析

    看完本文你会知道:

    1. HandlerThread的用法

    2. HandlerThread内部原理

    HandlerThread用法

    1.创建使用

    • 创建HandlerThread,HandlerThread其实就是继承的Thread类

    • 将HandlerThread的looper绑定到Handler

        //创建HandlerThread
        mHandlerThread = new HandlerThread("handlerThread-test");
        mHandlerThread.start();
        //将HandlerThread的looper绑定到Handler
        mHandler = new Handler(mHandlerThread.getLooper(), new Handler.Callback() {
               @Override
               public boolean handleMessage(Message msg) {
                        switch (msg.what) {
                                 case DELAY_1000:
                                          String str = (String) msg.obj;
                                          Log.d("handlerThread-test", "looper : DELAY_1000 " + str + "   处理线程:" + Thread.currentThread().getName());
                                          break;
                                 case DELAY_2000:
                                          String str1 = (String) msg.obj;
                                          Log.d("handlerThread-test", "looper : DELAY_2000 " + str1 + "   处理线程:" + Thread.currentThread().getName());
                                          break;
                                 case DELAY_3000:
                                          String str2 = (String) msg.obj;
                                          Log.d("handlerThread-test", "looper : DELAY_3000 " + str2 + "   处理线程:" + Thread.currentThread().getName());
                                          break;
                                 case DELAY_4000:
                                          String str3 = (String) msg.obj;
                                          Log.d("handlerThread-test", "looper : DELAY_4000 " + str3 + "   处理线程:" + Thread.currentThread().getName());
                                          break;
                        }
                        return false;
               }
        });
      

    2.测试

    • 在不同线程调度使用

        //测试
        new Thread(new Runnable() {
               @Override
               public void run() {
                        try {
                                 Thread.sleep(1000);
                        } catch (InterruptedException e) {
                                 e.printStackTrace();
                        }
                        asyncMessage(DELAY_1000, 0, "在子线程延时1s发送  调用线程:" + Thread.currentThread().getName());
               }
        }).start();
        asyncMessage(DELAY_2000, 2000, "在主线程延时2s发送  调用线程:" + Thread.currentThread().getName());
        mHandler.post(new Runnable() {
               @Override
               public void run() {
                        try {
                                 Thread.sleep(3000);
                        } catch (InterruptedException e) {
                                 e.printStackTrace();
                        }
                        asyncMessage(DELAY_3000, 0, "在post Runnable中sleep 3s  调用线程:" + Thread.currentThread().getName());
                        asyncMessage(DELAY_4000, 1000, "在DELAY_3000后延时1s发送  调用线程:" + Thread.currentThread().getName());
               }
        });
      
         private void asyncMessage(int what, int delay, String s) {
                  Message message = mHandler.obtainMessage();
                  message.what = what;
                  message.obj = s;
                  mHandler.sendMessageDelayed(message, delay);
         }
      
    • 结果:结果可以看出通过Handler对消息调度的处理,我们能在不同线程间进行通讯,并最终在HandlerThread异步处理

        handlerThread-test: looper : DELAY_1000 在子线程延时1s发送  调用线程:Thread-5   处理线程:handlerThread-test
        handlerThread-test: looper : DELAY_2000 在主线程延时2s发送  调用线程:main   处理线程:handlerThread-test
        handlerThread-test: looper : DELAY_3000 在post Runnable中sleep 3s  调用线程:handlerThread-test   处理线程:handlerThread-test
        handlerThread-test: looper : DELAY_4000 在DELAY_3000后延时1s发送  调用线程:handlerThread-test   处理线程:handlerThread-test
      

    3.退出

    private void threadDestory() {     
          if (mHandlerThread != null) {
                   mHandlerThread.quitSafely();
                   mHandlerThread = null;
          }
    }
    

    HandlerThread源码分析

    查看HandlerThread内部源码,会发现,其实就只有一点代码,接下来一起分析吧

    1. 构造函数中指定线程等级

         /**
         * Standard priority of application threads.
         * Use with {@link #setThreadPriority(int)} and
         * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
         * {@link java.lang.Thread} class.
         */
        public static final int THREAD_PRIORITY_DEFAULT = 0;
        
        ...
    
        public HandlerThread(String name) {
            super(name);
            mPriority = Process.THREAD_PRIORITY_DEFAULT;
        }
    

    2. Run方法中初始化looper

        * 并调用   onLooperPrepared(looper执行前执行,用于处理一些准备工作)
        *  Looper.myLooper();绑定当前线程Looper轮询器
        *  Looper.loop(); 开始轮询消息
    
         protected void onLooperPrepared() {
        }
    
        @Override
        public void run() {
            mTid = Process.myTid();
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            Looper.loop();
            mTid = -1;
        }
    

    3. 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;
        }
    

    4. 退出轮询,还记得Handler源码剖析里说的,Looper quit时会清理MessageQueue里面所有的消息

        public boolean quit() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quit();
                return true;
            }
            return false;
        }
    
        public boolean quitSafely() {
            Looper looper = getLooper();
            if (looper != null) {
            looper.quitSafely();
            return true;
            }
            return false;
        }
    

    相关文章

      网友评论

          本文标题:HandlerThread源码分析

          本文链接:https://www.haomeiwen.com/subject/vlplcqtx.html