HandlerThread相关问题总结
HandlerThread是什么
HandlerThread产生背景
开启Thread子线程进行耗时操作
多次创建和销毁线程是很耗系统资源的。
(为什么呢,因为java的线程是依托操作系统,线程的创建和销毁以及频繁切换都涉及到用户态和内核态的切换,以及线程上下文的保存和恢复,所以是比较耗资源的。)
HandlerThread 的特点
本质上就是封装了Handler的线程
- HandlerThread 本质是一个线程类,它继承自Thread
- HandlerThread 有自己的内部looper对象,可以进行loop循环
- 通过HandlerThread的looper对象传递给Handler对象,可以在handleMessage方法中执行异步任务
- 不会阻塞,减少了对性能的消耗,缺点是不能同时进行多任务的处理,需要等待进行,效率低。
这里的不会阻塞,指的是非UI线程,又想使用消息机制的那些操作。通过HandlerThread来执行是最合适的。
- 与线程池重并发不同,HandlerThread是一个串行队列,HandlerThread只有一个线程。
HandlerThread的用法
1.创建HandlerThread
HandlerThread handlerThread = new HandlerThread("handlerThread_name");
//2.必须先开启线程
handlerThread.start();
/**
* 3.设置callback
* 该callback运行于子线程
*/
class ChildCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
//在子线程中进行相应的网络请求
//通知主线程去更新UI
mUIHandler.sendMessage(msg1);
return false;
}
}
//4.子线程Handler
Handler childHandler = new Handler(handlerThread.getLooper(),new ChildCallback());
HandlerThread源码分析
首先HandlerThread继承自Thread,说明它是一个线程,肯定需要实现run方法。
那它又号称内部集成了Handler,我们知道Handler的运行离不开Looper,
所以在run方法里面通过Looper.prepare()
和Looper.loop()
开启一个Looper循环。
继承自Thread
public class HandlerThread extends Thread {
...
}
构造方法
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
* Constructs a HandlerThread.
* @param name
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
通过线程名称和优先级来创建一个HandlerThread.
run方法
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {//同步代码块,确保同一时刻只有一个线程可以访问mLooper
mLooper = Looper.myLooper();
notifyAll();//通知当前等待线程,主要是getLooper()方法里的wait方法
}
Process.setThreadPriority(mPriority);//设定线程优先级
onLooperPrepared();//空方法,留个用户自己重写
Looper.loop();//初始化数据接收,开启循环。
mTid = -1;
}
getLooper()方法
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {//同步代码块,如果looper没有创建成功,就一直阻塞,直到looper创建完毕。
while (isAlive() && mLooper == null) {
try {
//这个是没有设置TimeOut的Object:wait方法,无限期等待,必须是其他线程调用notify或者notifyAll才能唤醒。
//当run方法的mLooper对象创建完毕时,就会调用notifyAll方法唤醒。
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
quit和quitSafely方法
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;
}
quitsafely比quit更安全,各自的实现原理如下。
//Looper.java
public void quit() {
mQueue.quit(false);
}
public void quitSafely() {
mQueue.quit(true);
}
//MessageQueue.java
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
private void removeAllMessagesLocked() {
Message p = mMessages;
while (p != null) {
Message n = p.next;
p.recycleUnchecked();
p = n;
}
mMessages = null;
}
private void removeAllFutureMessagesLocked() {
final long now = SystemClock.uptimeMillis();
Message p = mMessages;
if (p != null) {
if (p.when > now) {
removeAllMessagesLocked();
} else {
Message n;
for (;;) {
n = p.next;
if (n == null) {
return;
}
if (n.when > now) {
break;
}
p = n;
}
p.next = null;
do {
p = n;
n = p.next;
p.recycleUnchecked();
} while (n != null);
}
}
}