对HandlerThread的理解

提示:阅读本文之前可先阅读Android个人笔记之Android的消息机制

HandlerThread本质上就是一个普通Thread,只不过内部建立了Looper.看下源码

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

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

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

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

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

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

    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}

由此看出HandlerThread除了有个优先级之外,与自己手动创建Looper的Thread并没有什么不同。这里有一个地方要理解一下,也许你已经发现了
run方法里面当mLooper创建完成后有个notifyAll(),getLooper()中有个wait(),这是为什么呢?因为mLooper在HandlerThread中执行,而我们的handler是在UI线程初始化的,也就是说,我们必须等到mLooper创建完成,才能正确的返回getLooper();wait(),notify()就是为了解决这两个线程的同步问题。

既然系统给我们提供了这么一个类,到底有什么好处呢?

HandlerThread的常规用法

  • 启动线程,构造参数:String代表线程名,priority代表优先级。优先级范围为-20到19,默认为0,优先级越高,获得的CPU资源更多,反之则越少。-20代表优先级最高,反之19最低。
mThread = new HandlerThread("handler_thread"); 
mThread.start();
  • 创建处理任务的mWorkHandler和更新UI的mUIHandler。
mWorkHandler = new Handler(mThread.getLooper());
mUIHandler = new Handler();
  • mWorkHandler与HandlerThread的Looper关联,并在handleMessage(Message msg)中处理任务,处理完之后通知mUIHandler对UI进行刷新。
  • 在合适的时机退出HandlerThread,比如activity中的onDestroy(),方法有quit()和quitSafely()

具体处理方式要看具体需求,不过总体思路跟上面三个步骤差不多。如果想处理多个任务。就发送多个消息,在mWorkHandler进行处理。

HandlerThread的特点

  • HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。
  • 开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。
    相比多次使用new Thread(){…}.start()这样的方式节省系统资源。
    但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。
  • HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。
  • 通过设置优先级就可以同步工作顺序的执行,而又不影响UI的初始化;

总结

HandlerThread比较适用于单线程+异步队列的场景,比如IO读写操作,耗时不多而且也不会产生较大的阻塞。对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。

你可能感兴趣的:(对HandlerThread的理解)