Handler源碼學習(一)流程
Handler源碼學習(二)Message對象池
Handler源碼學習(三)MessageQueue入隊插隊
消息池是全系統共用,上限為50個
private static final int MAX_POOL_SIZE = 50;
// sometimes we store linked lists of these things
/*package*/ Message next;
private static Message sPool;
//假設現在消息池為空,從new message開始,到這個message被取出使用后,準備回收
//準備工作:拿到同步鎖,避免線程不安全
//1.next = sPool,因為池中是空的,所以此時sPool其實是null
//2.spool = this,將當前這個message作為池中中下一個應該被復用的對象
//3.sPoolSize ++;將池子中的數量增加一,這個數量依然是全系統共享
void recycleUnchecked() {
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
//上面已經回收了一個message,在這里來獲取message,看看會發生什么
//同樣進入同步代碼塊
//1.判斷sPool是否是為空,如果池子為空,就直接new一個message
//上面已經回收過一個message了,這里應該不為空
//m =sPool;把池子里的這個message取出來
//2.sPool = m.next 將池中下一個復用的對象賦值為m.next,但是我們通過上面的代碼發現這個是null,先
//不管
//3.將m.next置為空,m.flags = 0 給了一個標記使用中
//4.從池子中減去
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();
}
上面的過程只有一個mesage,詳細解釋一下sPool和next,將sPool看成一個指針,通過next來將對象組成了一個鏈表,因為每次只需要從池子里拿一個對象,所以不需要關心池子里具體有多少個對象,而是拿出當前這個sPool所指向的這個對象就可以了,sPool從思路上理解就是通過左右移動來完成復用和回收
Obtain() -- 復用
MessageObtain(1).jpg
當調用Obtain()的時候讓sPool=next,因為第一個message.next就等于第二個message,從圖上看相當于sPool這個指針向后移動了一位,隨后會將第一個message.next的值置為空
![Uploading MessageRecycle_209561.jpg . . .]
如下圖
MessageObtain(2).jpg
現在這個鏈表看上去就斷了,如果in-use這個message使用完畢了,怎么回到鏈表中?
recycleUnchecked() -- 回收
再看回收的方法中的代碼,next = sPool,將當前sPool所指向的message對象賦值給in-use的next,然后sPool = this,將sPool指向第一個message對象
MessageRecycle.jpg
這樣,就將鏈表又恢復了~,而且不管是復用還是回收都是保證線程同步的,所以始終會形成一條鏈式結構