標籤:android開發 對象 線程 鏈表
在android系統中,message常在多線程之間資訊交流中用到,通過Handler來傳遞線程間的訊息(message).今天討論的是android中的message特性:對象池.
在android中,google對message有一句這樣的英文說明:
* <p class="note">While the constructor of Message is public, the best way to get
* one of these is to call {@link #obtain Message.obtain()} or one of the
* {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
* them from a pool of recycled objects.</p>
上文的意思是: 雖然message的構造方法是對外開放的(public),但是,我們要擷取一個message時候最好使用這個方法obtainMessage(),這個方法可以從一個可以複用的對象池中擷取你需要的message.
同上面的意思,我們可以知道,原來message內其實維護了一個對象池,當我們使用完一個message的時候,這個message很有可能就會儲存在這個對象池裡面,也就是說message裡面有一個對象池來儲存我們使用過的message.實際上,通過代碼,我們可以知道當對象池裡面沒有我們需要的message時候,會自動new 一個message的. 所以不必擔心obtainMessage()擷取不了message.
現在來看看android的message的對象池時如何設計的.實際上,message裡面的對象池其實是通過維護一個單項鏈表來實現的!看看下面就知道來.
在message裡面有一下幾個變數的聲明和定義:
/*package*/ Message next; private static final Object sPoolSync = new Object(); private static Message sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 50;
next 指向下一個可用的message;
sPoolSync主要用來同步用的,保證多安全執行緒;
Message sPool;這裡的sPool用來表示當前一個可用的message,請注意這是一個static修飾的message,
sPoolSize用來記錄當前message對象池有多少個messagel .
最後解釋一下: message裡面其即時維護來一個單項鏈表結構來儲存message對象的!next永來指向下一個message對象,這裡的sPool很顯然就是這個鏈表的表頭.這樣以來就可以通過表頭順序遍曆整個對象池裡面的message.
上面我說了,當通過這個方法obtainMessage()來擷取一個message時候,就會去對象池裡面找取(這裡就是去這個單向鏈表中找取),如果對象池裡面沒有我們需要的message,就會new一個message. 我們來看看代碼來證明我所說的.
public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); } 通過上面的代碼可以看出:如果鏈表不為null,就取鏈表頭的message,然後把鏈表頭部下移動. 否在就會new Message().
最後要說的是,當一個message用完了後是如何加入這個鏈表的呢? 通過檔案Message.java,你會發現在Message裡面還定義來一個public的方法:
public void recycle() { clearForRecycle(); synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } } 通過上面的代碼可以知道recycle方法其實就是將這個message加入到這個鏈表(加入到了頭部).那麼,這個方法時在何時調用的呢?
實際上,當通過Handler發送一個message的時候,其實是將這個message根據他的延時來決定他的位置,將其添加到一個隊列裡面的MessageQueue,操作這個MessageQueue不僅僅是這個Handler,還有這個Handler的Looper.
其實每一個Handler都是需要一個Looper的,往往我們建立一個Handler的時候其實是沒有指明他的Looper,不過他會自動擷取建立這個Handler的線程的Looper來作為自己的Looper,所以,在android中,往往沒有指明Handler的Looper,其實就是用主線程(就是我們常說的ui線程)的Looper.
剛才我們說了,Handler的Looper其實也操作MessageQueue的,實際上一個Looper就需要一個MessageQueue的,我個人的理解是:Looper的目的就是操作MessageQueue,而Handler控制著Looper和MessageQueue.
其即時這樣的: Handler往MessageQueue裡面加入需要處理的message,而Looper從MessageQueue裡面取出需要處理的message來開始處理流程.
在Looper裡面其實是通過調用方法loop()來取出需要處理的message,並處理,處理完畢時候就會調用這個message的recycle(),由此來將處理完畢的message加入到對象池的!
android對象池之Message