應(yīng)用場(chǎng)景
享元模式指的是在項(xiàng)目中使用對(duì)象池. 可避免頻繁的去創(chuàng)建某個(gè)類(lèi)的對(duì)象, 大大減少創(chuàng)建的對(duì)象, 降低進(jìn)程對(duì)內(nèi)存的占用.
最典型的場(chǎng)景是Android中的Message類(lèi), 一般情況下, app會(huì)頻繁的大量使用Message對(duì)象, 如果每次都去new一個(gè)新對(duì)象出來(lái)使用, 用后再通過(guò)GC進(jìn)行垃圾回收. 那很可能會(huì)導(dǎo)致頻繁的gc,影響程序的性能.
因此, android提供了一個(gè)Message對(duì)象池, 當(dāng)開(kāi)發(fā)者需要一個(gè)Message對(duì)象時(shí), 調(diào)用Message.obtain()從這個(gè)池子里取一個(gè)對(duì)象出來(lái)使用, 這樣做可以優(yōu)化一定的性能.
當(dāng)要得到一個(gè)對(duì)象時(shí), 推薦使用
Message msg = Message.obtain();
獲得一個(gè)Message對(duì)象.
而不要每次都
Message msg = new Message();
這樣去創(chuàng)建一個(gè)新的Message對(duì)象去使用.
Message的代碼分析
Message的對(duì)象池是通過(guò)一個(gè)鏈表實(shí)現(xiàn)的.
默認(rèn)最大長(zhǎng)度是50,
從鏈表中取對(duì)象時(shí),取的是頭節(jié)點(diǎn).
把不用的對(duì)象添加進(jìn)鏈表, 也是作為頭節(jié)點(diǎn)添加到鏈表中.
public final class Message implements Parcelable {
private static Message sPool; //指向Message對(duì)象池鏈表的頭節(jié)點(diǎn)
Message next; //指向鏈表頭的下一個(gè)節(jié)點(diǎn).
private static final int MAX_POOL_SIZE = 50;
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) { //如果鏈表存在的話
Message m = sPool; //取出鏈表的頭節(jié)點(diǎn)對(duì)象, 并返回這個(gè)頭節(jié)點(diǎn)對(duì)象
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
public void recycle() {
recycleUnchecked();
}
//對(duì)某一個(gè)不再使用的Message對(duì)象進(jì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) {//鏈表長(zhǎng)度小于50個(gè)的情況下
next = sPool;
sPool = this; //把當(dāng)前要回收的節(jié)點(diǎn)作為鏈表頭添加進(jìn)鏈表
sPoolSize++;
}
}
}
}
---DONE.---