Android 线程间通信 - Java 层 - MessagePool
线程间通信在 Android 系统中应用十分广泛,本文是一个系列文章,主要梳理了Android Java层的线程间通信机制-Handler
还是以一个简单的Handler示例开头
public void egHandler() {
Looper.prepare();
Looper.loop();
Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
// TODO; 处理 Event
}
};
new Thread() {
@Override
public void run() {
Message msg = Message.obtain(); // 注意: 此处和上篇文章中的示例不同
msg.what = 0;
handler.sendMessage(msg);
}
}.start();
}
为了避免重复的创建以及销毁 Message 对象带来的系统开销,Google 团队在Message.java
中搞了一个MessagePool,在MessagePool中缓存了定量的Message对象
上面示例中使用的Message.obtain()是从Pool中拿到一个message对象。
MessagePool
源码路径:frameworks/base/core/java/android/os/Message.java
在Message.java中定义了四个成员变量
// MessagePool 同步锁
public static final Object sPoolSync = new Object();
// MessagePool Node节点
private static Message sPool;
// MessagePool Node个数
private static int sPoolSize = 0;
// MessagePool 最大容量
private static final int MAX_POOL_SIZE = 50;
从MessagePool中获取一个message对象,需要调用obtain方法,该方法重载了多个
obtain message
Message.obtain()
public static Message obtain() {
// 上锁
synchronized (sPoolSync) {
if (sPool != null) {
// 从sPool链表拿出头节点
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
Message.obtain(Message orig)
public static Message obtain(Message orig) {
// 获取一个message
Message m = obtain();
// 将m和形参orig同步
m.what = orig.what;
m.arg1 = orig.arg1;
m.arg2 = orig.arg2;
m.obj = orig.obj;
m.replyTo = orig.replyTo;
m.sendingUid = orig.sendingUid;
m.workSourceUid = orig.workSourceUid;
if (orig.data != null) {
m.data = new Bundle(orig.data);
}
m.target = orig.target;
m.callback = orig.callback;
return m;
}
Message.obtain(Handler h)
public static Message obtain(Handler h) {
Message m = obtain();
// 单独为新msg设置handler
m.target = h;
return m;
}
另外还有一些构造方法,整体实现思路差不多。
recycle message
Message.recycle
public void recycle() {
if (isInUse()) {
// InUse中被释放会抛出异常
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
// 释放
recycleUnchecked();
}
Message.recycleUnchecked
@UnsupportedAppUsage
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
// 初始化flag,标记为InUse
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;
// 上锁,将需要释放的msg插入到链表头
synchronized (sPoolSync) {
// 注意这里,回收的过程中会判断当前链表的长度是否大于最大长度
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
recycle与recycleUnchecked的区别在于:
- recycleUnchecked 不会检查当前msg是否在使用中,而是会直接回收掉该msg,放在链表的头部
- recycle 会判断当前的msg是否在使用,在使用中会抛出异常,非使用中直接调用recycleUnchecked进行回收
另外,recycleUnchecked不支持app是否,App中只能是否recycle
Message.isInUse
// Message 中两个成员变量
/*package*/ static final int FLAG_IN_USE = 1 << 0;
/** If set message is asynchronous */
/*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
/*package*/ boolean isInUse() {
return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
}
Message.markInUse
@UnsupportedAppUsage
/*package*/ void markInUse() {
flags |= FLAG_IN_USE;
}
这个flag的判断方式我有点不理解,还不如直接用数字判断,例如flag = 1就是InUse,难道是为了判断的更快一点采用|、&
的方式?
理解为什么这么做的大佬在下面评论一下,不吝指出。
作者:lightingsui
链接:https://juejin.cn/post/7072737035357782023
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。