HandlerThread 之简单理解与使用-飞
发布时间: 2023-07-06

HandlerThread 顾名思义就是一种可以使用 Handler 的 Thread。日常开发中我们经常会通过创建一个 Thread 去执行任务,有多个任务就多创建几个线程实现,这时候可能出现线程同步的问题。不过有时候我们并不需要很强的并发性,只需保证按照顺序地执行各个任务即可,有什么好办法实现呢?第一反应想到的可能是通过 Executors.newSingleThreadExecutor() 方法来创建一个 SingleThreadExecutor,来统一所有的任务到一个线程中,然后按顺序执行。其实,除了这个方法之外,HandlerThread 也可以实现。

简单使用

首先创建一个 HandlerThreadActivity

public class HandlerThreadActivity extends BaseActivity {        private static final String TAG = "HandlerThreadActivity";    private Button mStartBtn;    private Handler mHandler;    private HandlerThread mHandlerThread;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_handler_thread);        mStartBtn = findViewById(R.id.start_btn);        mHandlerThread = new HandlerThread("THREAD_NAME");        mHandlerThread.start();        mHandler = new Handler(mHandlerThread.getLooper());        mStartBtn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mHandler.post(new Runnable()(舌战群儒的主人公是谁?舌战群儒的主人公是诸葛亮。舌战群儒典故的意思:舌战、激烈争辩;儒:指读书人。指同很多人辩论,并驳倒对方。) {                    @Override                    public void run() {                        Log.d(TAG, Thread.currentThread().getId() + " " + String.valueOf((Looper.myLooper() == Looper.getMainLooper())) + " 任务:" + this.hashCode());                        SystemClock.sleep(3000);                    }                });            }        });    }    @Override    protected void onDestroy() {        super.onDestroy();        mHandlerThread.quit();    }}

快速三击按钮,打印日志如下:


可以发现,三次不同的任务按开始的顺序执行,而且是运行在子线程中,那到底是怎么实现的呢?

源码解析
public class HandlerThread extends Thread {    int mPriority;    int mTid = -1;    Looper mLooper;    private @Nullable Handler mHandler;    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() {        // 获取线程 id        mTid = Process.myTid();        //构建一个 Looper        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        //设置线程优先级        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        // Looper 循环        mTid = -1;    }         // 获取当前线程的 Looper,    public Looper getLooper() {        if (!isAlive()) {            return null;        }               synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }     /**     * @return a shared {@link Handler} associated with this thread     * @hide 方法隐藏掉,无法调用     */    @NonNull    public Handler getThreadHandler() {        if (mHandler == null) {            mHandler = new Handler(getLooper());        }        return mHandler;    }     //线程退出方法,主要是调用 Looper.quit() 方法,不然一直在循环    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;    }}

通读下来,如果熟悉 Handler 原理的同学大概就明白 HandlerThread 的机制了:

HandlerThread 运行 start() 方法,回调 run() 方法。在 run() 方法中通过 Looper.prepare() 来创建消息队列,并通过 Looper.looper() 方法来开启消息循环。由于 Loop.loop() 是一个死循环,导致 run() 也是无线循环,因此当我们不需要使用 HandlerThread 的时候,要调用它的 quit() 方法或者 quiteSafely() 方法。结束语

这就是 HandlerThread 的大概原理啦,它在 Andr

微信