Handler源碼學習(二)Message對象池

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

這樣,就將鏈表又恢復了~,而且不管是復用還是回收都是保證線程同步的,所以始終會形成一條鏈式結構

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容