一、HandlerThread
一般想要在子线程中使用Handler,那么需要继承 Thread 类或者new Thread 对象,然后在 run() 调用Looper.prepare() 和 Looper.loop()。现在 HandlerThread 帮我们实现封装好了,省去这些麻烦的步骤,直接使用。
HandlerThread 是 Android 封装好的轻量级异步类,内部通过继承 Thread 和封装 Handler,从而使得创建新线程和其他线程进行通信更加方便。
作用:实现多线程;异步通信,消息传递。
优点:方便实现异步通信。
源码分析:
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;
}
...
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
...
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
...
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;
}
...
}
HandlerThread.java 文件只有 100 多行,非常的简洁。它继承了 Thread 类,那么是需要调用start() ,在 run() 中调用了 Looper.prepare(),为当前线程关联了 Looper。
getLooper():当调用此方法时,线程必须是存活状态,那么意味着其中一个条件:必须先调用 start(),后调用 getLooper()。而且如果mLooper为null,会 wait() 使当前线程等待,释放当前线程共享对象的锁,直到调用 notifyAll() 唤醒线程,继续往下执行。
quit():退出循环,但是也会终止执行中的任务,这样是不安全的。
quitSafely():当执行中的任务执行完成后,才退出循环。
二、Message.Obtain()
public final class Message implements Parcelable {
...
public static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
...
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
...
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
...
}
sPool 是 Message 类型,用来缓存 Message 对象,最多缓存 50 个对象。
在 Looper.loop() 中,handler 处理完 msg 会调用 msg.recycleUnchecked()。recycleUnchecked() 方法里面将用完的 msg 增加到缓存池。
优点:重复利用 Message 对象,减少每次都去堆内存开辟空间的时间,减少JVM垃圾回收,提高效率。
三、ThreadLocal
ThreadLocal 是解决并发的另外一种方案,不使用加锁同步就能解决线程不安全问题。
详细见另一篇文章:Java并发之ThreadLocal_如若、然的专栏-优快云博客
四、Linux 的 epoll+pipe 机制
待完成