我们从handle的recycle方法开始:
@Override
public void recycle(Object object) {
if (object != value) {
throw new IllegalArgumentException("object does not belong to handle");
}
stack.push(this);
}
然后进入stack.push:
void push(DefaultHandle<?> item) {
Thread currentThread = Thread.currentThread();
if (thread == currentThread) {
// The current Thread is the thread that belongs to the Stack, we can try to push the object now.
pushNow(item);
} else {
// The current Thread is not the one that belongs to the Stack, we need to signal that the push
// happens later.
pushLater(item, currentThread);
}
}
非常简单,thread是我们创建stack的时候保存的thread参数,当前线程和创建stack的线程是同一个线程就调用pushNow(item),我们现在是分析同线程,后面一篇文章再分析异线程,所以进入pushNow:
private void pushNow(DefaultHandle<?> item) {
if ((item.recycleId | item.lastRecycledId) != 0) {
throw new IllegalStateException("recycled already");
}
item.recycleId = item.lastRecycledId = OWN_THREAD_ID;
int size = this.size;
if (size >= maxCapacity || dropHandle(item)) {
// Hit the maximum capacity or should drop - drop the possibly youngest object.
return;
}
if (size == elements.length) {
elements = Arrays.copyOf(elements, min(size << 1, maxCapacity));
}
elements[size] = item;
this.size = size + 1;
}
首先看
if ((item.recycleId | item.lastRecycledId) != 0) {
throw new IllegalStateException("recycled already");
}
如果是第一次回收,recycleId和lastRecycleId都是0,否则只要有一个不为0,那么就说明回收过,就抛出已经回收过的异常。
然后正常的流程就是需要把recycleId和lastRecycleId赋值:
item.recycleId = item.lastRecycledId = OWN_THREAD_ID;
看这个OWN_THREAD_ID:
private static final int OWN_THREAD_ID = ID_GENERATOR.getAndIncrement();
也就是在一个Recycler类里面,这个OWN_THREAD_ID是唯一固定的。
返回。
有两种情况需要不回收然后return的:
if (size >= maxCapacity || dropHandle(item)) {
// Hit the maximum capacity or should drop - drop the possibly youngest object.
return;
}
size>=maxCapacity的时候,也就是大小已经超过最大大小了,放不下了。
第二种情况,dropHandle返回true的时候,也就是:
boolean dropHandle(DefaultHandle<?> handle) {
if (!handle.hasBeenRecycled) {
if ((++handleRecycleCount & ratioMask) != 0) {
// Drop the object.
return true;
}
handle.hasBeenRecycled = true;
}
return false;
}
handleRecycleCount就是目前回收对象的个数,ratioMask就是7(0X00000111),也就是说,每隔8个对象判断一次,表示只回收八分之一的对象。
最后看:
if (size == elements.length) {
elements = Arrays.copyOf(elements, min(size << 1, maxCapacity));
}
elements一开始不一定就分配maxCapacity的容量,如果容量满了,那就size<<1左移两位也就是两倍,然后和maxCapacity之间取一个最小的来扩容,把扩容的值又给elements,最后通过:
elements[size] = item;
this.size = size + 1;
将回收的对象放到elements里面。