从源码解析-Android中HandlerThread使用

HandlerThread详解
本文深入剖析了Android中的HandlerThread组件,探讨了其产生的背景、特点及使用场景,详细解读了源码实现,为开发者提供了一个清晰的多线程通信方案。

继上篇文章Android之Handler源码分析/Looper,Message,Messagequeue三者关系之后,现在来总结下HandlerThread。

产生背景

平时我们在进行多任务操作的时候,会开启多个线程,但是多次创建和销毁线程是很消耗系统资源的;

通常我们是在子线程里用Handler发消息将过程或者结果反馈给主线程;那如果是主线程要主动发消息去与子线程通信呢

HandlerThread是什么

HandlerThread本质上也是一个线程,因为继承了Thread类;不过与传统Thread不同的是它内部维护了一个Looper对象,这样HandlerThread相当于存在一个MessageQueue,用来存放消息,可以创建Handler发送和处理消息;然后Looper不断轮询,没有消息就阻塞,有消息就取出消息让Handler进行处理,那开发者始终就只用维护一个线程去执行耗时操作

HandlerThread特点

  • HandlerThread本质上是一个线程类,继承Thread
  • HandlerThread内部维护Looper对象,可以进行消息循环
  • 通过获取HandlerThread的Looper对象,将其传递给Handler对象,这样在主线程可以通过这个Handler对象发送消息,然后在handleMessage方法中执行耗时操作
  • HandlerThread执行任务不会阻塞,并且只有一个线程在允许,减少了对性能的消耗
  • HandlerThread是串行执行任务的,不能同时处理多任务

HandlerThread源码

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    //自己维护Looper对象
    Looper mLooper;

    /**
     * @param name 线程名
     */
    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    /**
     * Constructs a HandlerThread.
     * @param name 线程名
     * @param priority 线程优先级
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    /**
     * 如果需要在Looper循环之前做设置,可以重写这个方法操作
     */
    protected void onLooperPrepared() {
    }

    @Override
    public void run() {
        mTid = Process.myTid();
        //初始化looper
        Looper.prepare();
        synchronized (this) {
            //获取looper
            mLooper = Looper.myLooper();
            //这里主要是唤醒下面getLooper()方法中等待的线程
            notifyAll();
        }
        //设定线程优先级,减少内存泄漏的情况
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        //开启轮询
        Looper.loop();
        mTid = -1;
    }
    
    /**
     * 获取Looper对象,通常是创建Handler时候使用
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // 如果线程已经启动,就等待直到mLooper被创建
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    /**
     * 退出消息循环
     */
    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;
    }


    public int getThreadId() {
        return mTid;
    }
}

HandlerThread使用
 

    private final int MAIN_THREAD_WORK = 0X01;
    private final int THREAD_MAIN_WORK = 0X02;
    
    private  HandlerThread thread = new HandlerThread("handler-Thread");

    private ThreadHandler threadHandler;
    class ThreadHandler extends Handler{

        public ThreadHandler(Looper looper){
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //收到主线程消息,执行耗时操作
            while (true) {
                Log.d(TAG,"threadHandler");
                //模拟耗时操作执行完,发消息给主线程
                mainHandler.sendEmptyMessage(THREAD_MAIN_WORK);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    Handler mainHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //收到子线程消息,更新UI
            Log.d(TAG,"mainHandler");
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //先开启线程
        thread.start();
        //再实例化子线程的Handler
        threadHandler = new ThreadHandler(thread.getLooper());
        //通知子线程开始做耗时操作
        threadHandler.sendEmptyMessage(MAIN_THREAD_WORK);
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值