1什么是HandlerThread?
1.轻量级异步通信类
2.一个实现了Handler通信机制的线程 继承Thread
3.HandlerThread内部实现了Looper对象,可以进行Looper循环
4.HandlerThread将loop转到子线程中处理,将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅
5.开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。
相比多次使用new Thread(){…}.start()这样的方式节省系统资源。
6.HandlerThread将loop转到子线程中处理,将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。
开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。
相比多次使用new Thread(){…}.start()这样的方式节省系统资源。
7.但是由于每一个任务都将以队列的方式逐个被执行到(会把所有消息放入messageQuene,随后才执行handleMessage),一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。
8.HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。
通9.过设置优先级就可以同步工作顺序的执行,而又不影响UI的初始化
10.HandlerThread比较适用于单线程+异步队列的场景,比如IO读写操作,耗时不多而且也不会产生较大的阻塞。对于网络IO操作,HandlerThread并不适合,
11.HandlerThread 所做的就是在新开的子线程中创建了 Looper,
2 使用步骤
// 步骤1:创建HandlerThread实例对象
// 传入参数 = 线程名字,作用 = 标记该线程
HandlerThread mHandlerThread = new HandlerThread("handlerThread");
// 步骤2:启动线程
mHandlerThread.start();
// 步骤3:创建工作线程Handler & 复写handleMessage()
// 作用:关联HandlerThread的Looper对象、实现消息处理操作 & 与其他线程进行通信
// 注:消息处理操作(HandlerMessage())的执行线程 = mHandlerThread所创建的工作线程中执行
Handler workHandler = new Handler( handlerThread.getLooper() ) {
@Override
public boolean handleMessage(Message msg) {
...//消息处理
return true;
}
});
// 步骤4:使用工作线程Handler向工作线程的消息队列发送消息
// 在工作线程中,当消息循环时取出对应消息 & 在工作线程执行相关操作
// a. 定义要发送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的标识
msg.obj = "B"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
workHandler.sendMessage(msg);
// 步骤5:结束线程,即停止线程的消息循环
mHandlerThread.quit();
3 HandlerThread源码
handlerThread源码比较简单,我们看看核心的就好,
1:run()方法
1
run方法中的方法作用
mTid = Process.myTid(); // 1. 获得当前线程的id
Looper.prepare(); // 2. 创建1个Looper对象 & MessageQueue对象
synchronized关键字 // 3. 通过持有锁机制来获得当前线程的Looper对象。这样handlerThread是线程安全的
mLooper = Looper.myLooper();//是获取当前进程的looper对象
notifyAll();是唤起getLooper()中的wait()的。
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
} // 此处使用持有锁机制 + notifyAll() 是为了保证后面获得Looper对象前就已创建好Looper对象
/**
* This method returns the Looper associated with this thread. If this thread not been started
* or for any reason isAlive() returns false, this method will return null. If this thread
* has been started, this method will block until the looper has been initialized.
* @return The looper.
*/
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;
}
我们在看下quit和quitSafely方法
在看看quit()和quitSafely()最终调用的都是quit(方法)
这个是最终调用的方法
分别调用了下面的方法
removeAllMessagesLocked()方法的作用:历Message链表、移除所有信息的回调 & 重置为null
removeAllFutureMessagesLocked():
- 原理:先判断当前消息队列是否正在处理消息 用当前时间和message发送的时间做判断
-
a. 若不是,则类似分析removeAllMessagesLocked移除消息
-
b. 若是,则等待该消息处理处理完毕再使用分析removeAllMessagesLocked中的方式移除消息退出循环
- 退出方法安全与否(quitSafe() 或 quit()),在于该方法移除消息、退出循环时是否在意当前队列是否正在处理消息