Message(Message Pool)原始碼分析
前提概要
筆者有一段時間寫Message一直這麼寫:
Message msg=new Message();
msg.what=0;
handler.sendMessage(msg);
但是事實上,為了提高效率,我們應該複用Message:
Message msg=handler.obtainMessage();
msg.what=0;
handler.sendMessage(msg);
那麼在這個obtainMessage()中究竟是如何實現Message的複用的呢?
儲存結構是怎樣,執行緒併發如何處理等。
原始碼解析
獲取邏輯
首先由obtainMessage()為入口,然後可以即進入到Message.obtain()方法:
public final Message obtainMessage()
{
return Message.obtain(this);
}
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
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();
}
private static final Object sPoolSync = new Object();
private static Message sPool;
從obtain()原始碼中我們可以看到,所謂的MessagePool,不過就是一個連結串列。
對執行緒併發的處理也便是用synchronized 對sPoolSync 這個final物件加鎖。
而此處為什麼不用物件鎖或者類鎖呢?
由於是靜態方法,物件可能不存在,所以不能用物件鎖。
用類鎖雖然也可以實現,但是MessagePool的邏輯和Message類本身關係不大,用了一方面不是很恰當,另一方面也限制了Message類的擴充。
回收邏輯
獲取的邏輯基本就這樣了,再看下回收的邏輯,這裡我們直接看到MessageQueue.removeMessages()和其中呼叫到的Message.recycleUnchecked():
void removeMessages(Handler h, int what, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
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 = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
可以看到,recycleUnchecked()就是Message中另一處呼叫到synchronize(sPoolSync)的地方。對所謂“MessagePool”的處理也就這兩處。recycleUnchecked()中的邏輯便是把Message中的內容清空。
在MessageQueue中removeMessage的邏輯非常簡單,首先把要刪除的Message清空,然後把連結串列中後面的節點放到前面來。(並沒有刪除物件,只是清空了內容放到連結串列後面而已)
相關文章
- Android的Message Pool是個什麼鬼——原始碼角度分析 .Android原始碼
- android原始碼解析--MessageAndroid原始碼
- Android開發Message原始碼分析【享元模式|物件池】Android原始碼模式物件
- Android Handler Looper Message 詳細分析AndroidOOP
- javascript message事件JavaScript事件
- ActiveMQ - message cursorMQ
- RocketMQ原始碼解析之訊息消費者(consume Message)MQ原始碼
- 深入原始碼解析Android中的Handler,Message,MessageQueue,Looper原始碼AndroidOOP
- Android Handler機制之Message及Message回收機制Android
- 修改 commit messageMIT
- Flash Message For Laravel 5Laravel
- Android Message解析Android
- 【Exception】:own error messageExceptionError
- Handler、Looper、Message隨筆OOP
- SQL*Net message from clientSQLclient
- Error message: ORA-48913Error
- {"error":400,"message":"over quota"}Error
- 再談Handler、Looper、Message、MessageQueue基礎流程分析OOP
- SQL*Net message from client 事件產生的原因分析SQLclient事件
- WebSphere Message Broker V7 上的影響分析Web
- 直播網站原始碼,vant中Dialog的使用,如何修改Message字號大小網站原始碼
- Git commit message 規範GitMIT
- SMB(Server Message Block) Protocal ResearchServerBloC
- ORA-24033: no recipients for message
- jquery ui Message 簡單使用jQueryUI
- hs message to agent'阻塞會話會話
- WebSphere Message Broker HttpInput 節點WebHTTP
- POJ-2141 Message Decowding-奶牛密碼密碼
- open-ethereum-pool以太坊礦池原始碼分析(2)API分析原始碼API
- 關於IPC-Message通訊
- “reliable message”事件引發的思考事件
- Message,MessageQueue,Looper,Handler詳解OOP
- 小知識分享:顯示MESSAGE
- PTP ACS9522 Message rate
- 怎樣使用程式碼得到bean:message 中的內容?Bean
- open-ethereum-pool以太坊礦池原始碼分析(1)-main入口分析原始碼AI
- MQTT 遺囑訊息(Will Message)的使用MQQT
- unity 3種message訊息管理使用Unity