模式定义
运用共享技术有效的支持大量细粒度的对象
使用场景
- 系统中有大量对象, 这些对象消耗大量内存
- 对象的状态大部分可以外部化。
- 对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替
- 系统不依赖于这些对象身份,这些对象是不可分辨的
例子
- Message.obtain
private static int sPoolSize = 0;
Message next;
private static final Object sPoolSync = new Object();
private static Message sPool;
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();
}
我们可以看到message要么是从最后new Message返回一个新的对象,要么返回sPool。当返回sPool时就是返回已创建的重复对象。再理解为啥sPool就是重复对象时,我们先看明白Message这个单链表对象
- Message包含一个next的Message对象。sPoolSize表示个数,以此形成单链表结构
单链表的取出
在obtain方法中
Message m = sPool —m等于单链表
sPool = m.next —sPool单链表舍弃表头元素
m.next = null; —m舍弃除表头之外的所有元素
m.flags = 0; —flag置0标记
sPoolSize–; —单链表大小减1
这样就取出来了单链表的头元素并返回,而我们的单链表sPool舍弃表头。这样就完成了元素的复用。当然这里只是取出,接下来我们看插入
单链表的插入
插入的操作是在Message回收的时候
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
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++;
}
}
}
recycle判断Message对象是否正在被使用,如果是则刨除异常,否则开始进行recycleUnchecked单链表插入操作。插入之前先清空了各个参数。
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
总结
优点:
大大减少对象的创建,降低系统的内存,使效率提高
缺点:
提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱