前言
每当创建HandlerThread对象后,调用它的start()方法,一个带有Handler消息循环机制的工作线程即开始它的工作,而我们要做的就是向它内部的MessageQueue对象发送Message对象、这样我们发送过去的消息将会在HandlerThread对象所在的工作线程中得到执行。在HandlerThread中,有两个方法:
1、一个是用于获取HandlerThread对象所在工作线程的Looper对象的方法->getLooper()方法
2、另一个是用于获取HandlerThread对象持有的Handler对象,该Handler对象是与HandlerThread对象所在的线程绑定在一起的
getThreadHandler()方法分析
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
用于获取当前HandlerThread对象所在工作线程的Handler对象,@hide修饰,我们无法自然调用
1、Handler对象未创建,执行创建逻辑
HandlerThread对象持有的mHandler如果为null,说明Handler对象还没有创建,此时执行创建Handler的逻辑(先获取当前工作线程中的Looper对象,再创建Handler对象)
2、向调用者返回创建好的Handler对象
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;
}
用于获取当前工作线程中的Looper对象的方法
1、判断当前工作线程的状态
当线程状态为0时,代表线程死亡,isAlive()方法位于父类Thread类中,当线程已经死亡,getLooper()整个方法会返回null
2、获取当前HandlerThread作为对象锁后执行的代码块
调用此代码块的线程需持有当前HandlerThread对象锁,才能继续执行此代码块,为什么要在这里加锁呢?还记得在创建Looper对象的时候,也加了同一个HandlerThread对象锁?加a monitor lock的目的是为了:保证其他线程获取到HandlerThread中创建的Looper对象。
当HandlerThread中的Looper对象还没有创建时,其他线程就先执行到此getLooper()方法中,其他线程先获取到当前HandlerThread对象锁,然后进行while循环中,接着是一个Object的wait()方法的调用,会导致其他线程释放当前HandlerThread对象锁,其他线程进入WAITING状态,这样接下来当前HandlerThread对象代表的工作线程就可以去执行创建Looper对象的工作,创建完后,通过notifyAll()方法通知所有处于WAITING状态的其他线程继续运行,这样就可以保证所有的其他线程一定可以获取到一个再HandlerThread对象代表的工作线程中已经创建好的一个Looper对象。
3、向其他线程返回Looper对象
isAlive()方法分析
public final boolean isAlive() {
return nativePeer != 0;
}
用于判断当前线程的存活状态,位于Thread类中,禁止重写,它返回了线程的存活状态,只要不是0就是代表线程存活着,当nativePeer为0时,代表Thread对象已经死亡
private volatile long nativePeer;
该实例变量在哪被赋值的?这里留下疑问
总结
1、Thread对象即表示操作系统层面的实际线程,本身Thread对象也是Java中的一个对象,所以它也有对应的a monitor lock,所以当前工作线程可以持有HandlerThread对象的monitor lock也不足为奇了
2、留给我们用来创建HandlerThread对象所属的Handler对象时,只要调用它的getLooper()方法再去创建一个Handler对象即可,此时每一个Handler对象都是归属于HandlerThread对象所在的工作线程,我们利用这些Handler对象可以向HandlerThread对应的线程中发送需要执行的任务
3、HandlerThread对象对应的工作线程因为使用了Handler机制,所以当MessageQueue中没有消息时,此工作线程完全不占用CPU时间片,所以我们可以不将HandThread退出,这样在一个App进程中就有一个可以随时待命的工作线程用来执行耗时任务,随需而用