前言
本章学习Netty对象池。
- 如何使用Netty对象池,实现对象的创建和回收
- Netty如何抽象对象池
- Netty如何实现对象池
- 如何处理同一个对象在不同线程创建和回收的场景
一、如何使用Netty对象池
Item是一个普通对象,这个对象由对象池管理。
public static class Item {
// 类变量,一个Item对象池
private static final ObjectPool<Item> pool = ObjectPool.newPool(new ObjectPool.ObjectCreator<Item>() {
@Override
public Item newObject(ObjectPool.Handle<Item> handle) {
return new Item(handle);
}
});
// 普通的业务属性
private int id;
// 对象回收钩子
private final ObjectPool.Handle<Item> handle;
/**
* 私有构造方法
*/
private Item(ObjectPool.Handle<Item> handle) {
this.handle = handle;
}
/**
* 从对象池获取item
*/
public static Item getInstance() {
return pool.get();
}
/**
* 回收
*/
public void recycle() {
this.handle.recycle(this);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
接着使用对象池创建对象和回收对象。
@Test
public void test() {
Item item01 = Item.getInstance(); // 池中没有对象缓存,创建了一个新的对象
item01.setId(1);
System.out.println(item01); // 5c7fa833
item01.recycle(); // 使用handle钩子回收item01
item01 = Item.getInstance(); // 重新从池中获取一个对象
System.out.println(item01); // 5c7fa833
System.out.println(item01.getId()); // 1
}
二、对象池抽象结构
Netty针对对象池,设计了一套自己的抽象结构,包括对象池、对象创建、对象回收,这三个抽象定义都在ObjectPool类中。
1、对象池
ObjectPool抽象类,是对象池的顶层抽象,需要子类实现一个get方法。如果池内有对象,则直接通过get方法返回,否则需要通过ObjectCreator#newObject(Handle)方法创建一个新对象返回。
/**
* Light-weight object pool.
*
* @param <T> the type of the pooled object
*/
public abstract class ObjectPool<T> {
ObjectPool() { }
/**
* Get a {@link Object} from the {@link ObjectPool}. The returned {@link Object} may be created via
* {@link ObjectCreator#newObject(Handle)} if no pooled {@link Object} is ready to be reused.
*/
public abstract T get();
}
2、对象创建
ObjectCreator是对象创建的抽象接口,需要实现一个newObject方法,传入Handle,创建一个新对象,之后这个对象可以被Handle#recycle回收。言外之意,对象需要持有Handle,在未来某一时刻通过Handle可以回收当前实例到ObjectPool。
/**
* Creates a new Object which references the given {@link Handle} and calls {@link Handle#recycle(Object)} once
* it can be re-used.
*
* @param <T> the type of the pooled object
*/
public interface ObjectCreator<T> {
/**
* Creates an returns a new {@link Object} that can be used and later recycled via
* {@link Handle#recycle(Object)}.
*/
T newObject(Handle<T> handle);
}
3、对象回收
Handle会在ObjectCreator创建对象时传入,客户端需要通过操作Handle的recycle方法回收对象。
/**
* Handle for an pooled {@link Object} that will be used to notify the {@link ObjectPool} once it can
* reuse the pooled {@link Object} again.
* @param <T>
*/
public interface Handle<T> {
/**
* Recycle the {@link Object} if possible and so make it ready to be reused.
*/
void recycle(T self);
}
三、Netty实现对象池
Netty针对上面的这套抽象接口,实现了自己的一个轻量级对象池,这个轻量级对象池的实现是ObjectPool的静态内部类RecyclerObjectPool。
private static final class RecyclerObjectPool<T> extends ObjectPool<T> {
private final Recycler<T> recycler;
RecyclerObjectPool(final ObjectCreator<T> creator) {
recycler = new Recycler<T>() {
@Override
protected T newObject(Handle<T> handle) {
return creator.newObject(handle);
}
};
}
@Override
public T get() {
return recycler.get();
}
}
可以看到,创建一个RecyclerObjectPool,需要传入ObjectCreator接口的实现类,此外不需要提供其他方法。而RecyclerObjectPool内部其实是创建了一个Recycler,Recycler借助ObjectCreator可以在池内无缓存对象时创建对象,全部委托Recycler实现了对象池。
此外Netty在ObjectPool提供了一个静态方法,用于创建RecyclerObjectPool。
/**
* Creates a new {@link ObjectPool} which will use the given {@link ObjectCreator} to create the {@link Object}
* that should be pooled.
*/
public static <T> ObjectPool<T> newPool(final ObjectCreator<T> creator) {
return new RecyclerObjectPool<T>(ObjectUtil.checkNotNull(creator, "creator"));
}
四、Recycler
Recycler是对象池获取对象的入口,先来看看类变量。
首先最关键的是一个FastThreadLocal实例threadLocal,每个线程管理一个Stack实例,这个Stack是真正的池。
private final FastThreadLocal<Stack<T>> threadLocal = new FastThreadLocal<Stack<T>>() {
@Override
protected Stack<T> initialValue() {
return new Stack<T>(Recycler.this, Thread.currentThread(), maxCapacityPerThread, maxSharedCapacityFactor,
interval, maxDelayedQueuesPerThread, delayedQueueInterval);
}
@Override
protected void onRemoval(Stack<T> value) {
if (value.threadRef.get() == Thread.currentThread()) {
if (DELAYED_RECYCLED.isSet()) {
DELAYED_RECYCLED.get().remove(value);
}
}
}
};
另外,考虑到对象的创建和回收可能不在同一个线程中完成,对象池就变得复杂了。这里还有一个FastThreadLocal实例DELAYED_RECYCLED,保存了当前线程stack帮助其他线程stack回收的容器WeakOrderQueue。言外之意,如线程A的Stack分配了实例X,线程B的Stack回收了实例X,这个FastThreadLocal针对线程B而言,Map的key是线程A的Stack,value是线程B创建的WeakOrderQueue容器,用于存储帮助线程A的Stack回收的对象。
// 其他线程的stack实例 - 线程帮助其他线程的stack回收的对象放在WeakOrderQueue容器中
private static final FastThreadLocal<Map<Stack<?>, WeakOrderQueue>> DELAYED_RECYCLED =
new FastThreadLocal<Map<Stack<?>, WeakOrderQueue>>() {
@Override
protected Map<Stack<?>, WeakOrderQueue> initialValue() {
return new WeakHashMap<Stack<?>, WeakOrderQueue>();
}
};
Recycler的成员变量都是为了约束对象池的大小,防止对象池膨胀。
private final int maxCapacityPerThread; // 4096
private final int maxSharedCapacityFactor; // 2
private final int interval; // 8
private final int maxDelayedQueuesPerThread; // 核数*2
private final int delayedQueueInterval; // 8
- maxCapacityPerThread:由于对象池是基于FastThreadLocal实现的线程局部缓存,为了防止缓存过多实例,maxCapacityPerThread是控制一个Stack可以存放多少缓存实例。
- maxSharedCapacityFactor:一个因子,用于计算其他线程帮助当前线程回收实例个数的上限。
- interval/delayedQueueInterval:为了防止对象池膨胀,并不是每次回收对象都会重新放入对象池,对于后面介绍的各类容器,一般是每8次才会真正缓存一次。
- maxDelayedQueuesPerThread:每个线程最多能帮助核数*2个线程回收。
Recycler的get方法是对象池的入口方法。借助threadlocal获取当前线程对应的Stack实例,通过操作Stack得到Handle和Handle对应的value(客户端对象实例)。
public final T get() {
// 默认4096
if (maxCapacityPerThread == 0) {
return newObject((Handle<T>) NOOP_HANDLE);
}
// 获取当前线程的Stack
Stack<T> stack = threadLocal.get();
// 获取Handle
DefaultHandle<T> handle = stack.pop();
// 如果stack中有Handle,直接返回缓存的对象,否则创建Handle
if (handle == null) {
// 创建DefaultHandle 等价于 handle = new DefaultHandle<>(stack)
handle = stack.newHandle();
// 调用RecycleObjectPool构造方法中的匿名类的newObject方法,实际上是客户端实现的匿名ObjectCreator
handle.value = newObject(handle);
}
return (T) handle.value;
}
五、DefaultHandle
DefaultHandle是Netty对象池给客户端的一个回收对象的钩子(见第一节的案例)。
private static final class DefaultHandle<T> implements Handle<T> {
int lastRecycledId;
int recycleId;
boolean hasBeenRecycled;
Stack<?> stack;
Object value;
DefaultHandle(Stack<?> stack) {
this.stack = stack;
}
@Override
public void recycle(Object object) {
if (object != value) {
throw new IllegalArgumentException("object does not belong to handle");
}
Stack<?> stack = this.stack;
if (lastRecycledId != recycleId || stack == null) {
throw new IllegalStateException("recycled already");
}
stack.push(this);
}
}
成员变量value是客户端创建的对象,由对象池管理。recycle方法由客户端调用,将DefaultHandle放入Stack。
六、Stack
先对照Stack图例和成员变量大致了解一下它的结构。
private static final class Stack<T> {
// Recycler属于一个RecyclerObjectPool,可以认为stack属于某个对象池实例
final Recycler<T> parent;
// userModel -> handle -> stack -> thread
final WeakReference<Thread> threadRef;
// 其他线程回收当前线程创建的对象的个数上限 = max(4096/2, 16)
final AtomicInteger availableSharedCapacity;
// 允许x个线程帮忙回收(WeakOrderQueue的最大个数)= 核数 * 2
private final int maxDelayedQueues;
// stack可以存储的DefaultHandle数量上限
// 相当于当前线程可以存储的DefaultHandle上限,因为Stack都是由ThreadLocal控制的
private final int maxCapacity;
// handle回收的循环计数器,遇interval(8)变0
private int handleRecycleCount;
// 默认为8,每次尝试回收handle都会通过handleRecycleCount计数,当handleRecycleCount<8会丢弃
private final int interval;
// 和interval类似,但是是异线程回收到WeakOrderQueue时的阈值,默认也是8
private final int delayedQueueInterval;
// 存储DefaultHandle
DefaultHandle<?>[] elements;
// elements里实际元素的个数
int size;
// 由当前stack创建的对象,其他线程回收,这些实例保存在WeakOrderQueue中
private WeakOrderQueue cursor, prev; // 消费WeakOrderQueue进度 双指针
private volatile WeakOrderQueue head; // 存储WeakOrderQueue的头节点
}
大多数成员变量和Recycler一样,为了防止对象池膨胀由Recycler传入。重点关注几个成员变量:
- elements:当前线程(Stack实例是ThreadLocal,可以认为是当前线程)缓存的Handle实例数组。初始容量256。
- head:WeakOrderQueue组成的链表,存储其他线程帮助当前线程回收的Handle实例。
- cursor/prev:当前Stack从WeakOrderQueue链表消费获取Handle的进度,这里是双指针。
- threadRef:由于Stack是基于ThreadLocal操作的,这里存储的是对应线程的虚引用。使用虚引用的原因是:假设当前Stack对应ThreadA,ThreadB客户端持有ThreadA分配出去的对象,这个客户端对象持有Handle,Handle会持有Stack,Stack如果强引用ThreadA会导致ThreadA无法回收。
- handleRecycleCount/interval:handleRecycleCount是一个循环计数器,最大值等于interval,初始值等于interval,每回收一个Handle加1。当handleRecycleCount小于interval时,Handle不会真的被放回池中,防止对象池膨胀。interval默认为8。
1、获取对象
pop方法用于从Stack中获取缓存的DefaultHandle。优先从当前线程回收的elements数组中取,如果elements数组为空,尝试从WeakOrderQueue中移动一些DefaultHandle到elements数组中,然后再从elements数组取。
DefaultHandle<T> pop() {
int size = this.size;
// 当前线程没有缓存Handle,elements数组中没有元素
if (size == 0) {
// 尝试从WeakOrderQueue中获取
if (!scavenge()) {
return null;
}
size = this.size;
if (size <= 0) {
return null;
}
}
// 当前线程有缓存Handle,直接从elements数组中获取
size --;
DefaultHandle ret = elements[size];
elements[size] = null;
this.size = size;
if (ret.lastRecycledId != ret.recycleId) {
throw new IllegalStateException("recycled multiple times");
}
ret.recycleId = 0;
ret.lastRecycledId = 0;
return ret;
}
如果elements数组为空,scavenge方法会尝试从cursor遍历WeakOrderQueue链表,调用WeakOrderQueue的transfer方法将其他线程帮助当前线程Stack回收的对象实例,放入当前Stack的elements数组中。
private boolean scavenge() {
// 从cursor遍历WeakOrderQueue链表,尝试获取一些DefaultHandle放入elements数组
if (scavengeSome()) {
return true;
}
// 如果从WeakOrderQueue获取DefaultHandle失败,重置cursor和prev指针
prev = null;
cursor = head;
return false;
}
private boolean scavengeSome() {
WeakOrderQueue prev;
WeakOrderQueue cursor = this.cursor;
// cursor指针为空,初始化两个指针
if (cursor == null) {
prev = null;
cursor = head;
if (cursor == null) {
return false;
}
} else {
prev = this.prev;
}
boolean success = false;
do {
// 尝试从其他线程回收的WeakOrderQueue中获取handle到自己的elements中
if (cursor.transfer(this)) {
success = true;
break;
}
WeakOrderQueue next = cursor.getNext();
// 如果WeakOrderQueue引用的线程已经被回收,将这个WeakOrderQueue里的所有Handle移动到当前Stack的elements数组
if (cursor.get() == null) {
if (cursor.hasFinalData()) {
for (;;) {
if (cursor.transfer(this)) {
success = true;
} else {
break;
}
}
}
// 将cursor指向的被回收的线程的WeakOrderQueue从链表中移除
if (prev != null) {
cursor.reclaimAllSpaceAndUnlink();
prev.setNext(next);
}
} else {
prev = cursor;
}
cursor = next;
} while (cursor != null && !success);
this.prev = prev;
this.cursor = cursor;
return success;
}
2、归还对象
归还对象的入口是DefaultHandle的recycle方法,由客户端调用。比如PooledByteBuf抽象类,就使用到了对象池,当ByteBuf引用计数为0会触发deallocate方法,最后会调用DefaultHandle的recycle方法。因为PooledByteBuf并没有实际持有资源,只是盛放资源的容器对象(真正的资源是16MB的memory内存块),所以使用对象池可以减少new对象的开销和GC。
@Override
protected final void deallocate() {
if (handle >= 0) {
final long handle = this.handle;
this.handle = -1;
memory = null;
chunk.arena.free(chunk, tmpNioBuf, handle, maxLength, cache);
tmpNioBuf = null;
chunk = null;
recycle();
}
}
private void recycle() {
// DefaultHandle#recycle(PooledByteBuf)
recyclerHandle.recycle(this);
}
DefaultHandle的recycle方法,调用Stack的push方法将DefaultHandle实例放入Stack。
void push(DefaultHandle<?> item) {
Thread currentThread = Thread.currentThread();
// 如果是当前线程创建的当前stack,且是当前线程在回收Handle,直接放入elements数组
if (threadRef.get() == currentThread) {
pushNow(item);
}
// 如果是其他线程创建的当前stack,但是由当前线程回收,放入WeakOrderQueue
// 并将WeakOrderQueue插入其他线程的stack的WeakOrderQueue链表的头部
else {
pushLater(item, currentThread);
}
}
pushNow方法将DefaultHandle直接放入当前stack的elements数组,但是有可能会丢弃这个Handle,防止对象池过度膨胀。
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;
// 如果元素个数已经超过4096 或 dropHandle判断需要丢弃这个元素来控制对象池大小
if (size >= maxCapacity || dropHandle(item)) {
return;
}
if (size == elements.length) {
elements = Arrays.copyOf(elements, min(size << 1, maxCapacity));
}
elements[size] = item;
this.size = size + 1;
}
/**
* 判断是否需要丢弃handle
* 构造时handleRecycleCount=interval=8
* 第一次不会被丢弃,2-8次会被丢弃,第九次不会被丢弃
*/
boolean dropHandle(DefaultHandle<?> handle) {
if (!handle.hasBeenRecycled) {
if (handleRecycleCount < interval) {
handleRecycleCount++;
// Drop the object.
return true;
}
handleRecycleCount = 0;
handle.hasBeenRecycled = true;
}
return false;
}
pushLater方法将DefaultHandle放入WeakOrderQueue,如果是新的WeakOrderQueue,会将WeakOrderQueue插入stack的WeakOrderQueue链表头部。WeakOrderQueue.DUMMY认为是一个空实现,并不能实际存放元素。当DELAYED_RECYCLED中当前线程帮助回收的stack超过16个(或认为是线程个数),就不会继续回收了。
private void pushLater(DefaultHandle<?> item, Thread thread) {
Map<Stack<?>, WeakOrderQueue> delayedRecycled = DELAYED_RECYCLED.get();
WeakOrderQueue queue = delayedRecycled.get(this);
if (queue == null) {
// 如果当前线程已经帮16个线程回收了,不会再帮其他线程回收
if (delayedRecycled.size() >= maxDelayedQueues) {
delayedRecycled.put(this, WeakOrderQueue.DUMMY);
return;
}
// 如果stack对应的WeakOrderQueue不存在,则创建并插入stack的WeakOrderQueue链表头部
// 这里WeakOrderQueue也存在丢弃策略,所以可能返回空
if ((queue = newWeakOrderQueue(thread)) == null) {
return;
}
delayedRecycled.put(this, queue);
} else if (queue == WeakOrderQueue.DUMMY) {
return;
}
queue.add(item);
}
private WeakOrderQueue newWeakOrderQueue(Thread thread) {
return WeakOrderQueue.newQueue(this, thread);
}
static WeakOrderQueue newQueue(Stack<?> stack, Thread thread) {
if (!Head.reserveSpaceForLink(stack.availableSharedCapacity)) {
return null;
}
// 将stack和当前回收线程放入WeakOrderQueue
final WeakOrderQueue queue = new WeakOrderQueue(stack, thread);
// 插入stack的WeakOrderQueue链表,作为头节点
stack.setHead(queue);
return queue;
}
七、WeakOrderQueue
WeakOrderQueue继承WeakReference虚引执行回收的线程,内部用链表(Link)+数组(Link#elements)的方式存储协助回收线程回收的DefaultHandle。
private static final class WeakOrderQueue extends WeakReference<Thread> {
// Link链表
private final Head head;
private Link tail;
// 指向下一个Queue
private WeakOrderQueue next;
// 一个id标志
private final int id = ID_GENERATOR.getAndIncrement();
// 丢弃策略同Stack interval默认为8 handleRecycleCount初始为8 取值范围0-8
private final int interval;
private int handleRecycleCount;
private WeakOrderQueue(Stack<?> stack, Thread thread) {
super(thread);
tail = new Link();
head = new Head(stack.availableSharedCapacity);
head.link = tail;
interval = stack.delayedQueueInterval;
handleRecycleCount = interval;
}
private static final class Head {
// 最大容量 默认 2048 = Stack#availableSharedCapacity
private final AtomicInteger availableSharedCapacity;
// 实际头节点
Link link;
}
static final class Link extends AtomicInteger {
// 16个Handle
final DefaultHandle<?>[] elements = new DefaultHandle[LINK_CAPACITY];
// AtomicInteger作为写index,是下一个可以插入elements的下标
// readIndex作为读index,是下一个可以获取elements的下标
int readIndex;
// next指针
Link next;
}
}
其中Link有读写两个index,继承AtomicInteger作为写index,代表下次可插入elements数组的下标;readIndex代表下次可以获取的Handle位于elements数组的下标。
WeakOrderQueue的关键方法有两个,一个是add方法将Handle存储到Link中,一个是transfer方法选择一个Link中的所有Handle放入指定的Stack的elements中。
add方法逻辑比较简单,可以看到WeakOrderQueue和Link都有自己的丢弃策略,前者与Stack类似,后者是通过最大容量Stack#availableSharedCapacity限制的。
void add(DefaultHandle<?> handle) {
handle.lastRecycledId = id;
// Queue丢弃策略
if (handleRecycleCount < interval) {
handleRecycleCount++;
return;
}
handleRecycleCount = 0;
Link tail = this.tail;
int writeIndex;
// 如果尾Link已经满了,尝试创建新的Link接入
if ((writeIndex = tail.get()) == LINK_CAPACITY) {
// Link丢弃策略
Link link = head.newLink();
if (link == null) {
return;
}
this.tail = tail = tail.next = link;
writeIndex = tail.get();
}
tail.elements[writeIndex] = handle;
handle.stack = null;
tail.lazySet(writeIndex + 1);
}
Link newLink() {
return reserveSpaceForLink(availableSharedCapacity) ? new Link() : null;
}
/**
* 如果 availableSharedCapacity < LINK_CAPACITY(16),直接返回false,丢弃
* 否则 尝试 availableSharedCapacity = availableSharedCapacity - LINK_CAPACITY(16)
*/
static boolean reserveSpaceForLink(AtomicInteger availableSharedCapacity) {
for (;;) {
int available = availableSharedCapacity.get();
if (available < LINK_CAPACITY) {
return false;
}
if (availableSharedCapacity.compareAndSet(available, available - LINK_CAPACITY)) {
return true;
}
}
}
transfer方法比较长,主要逻辑就是扩容+数据迁移。
boolean transfer(Stack<?> dst) {
Link head = this.head.link;
if (head == null) {
return false;
}
if (head.readIndex == LINK_CAPACITY) {
if (head.next == null) {
return false;
}
head = head.next;
this.head.relink(head);
}
final int srcStart = head.readIndex;
int srcEnd = head.get();
final int srcSize = srcEnd - srcStart;
if (srcSize == 0) {
return false;
}
final int dstSize = dst.size;
final int expectedCapacity = dstSize + srcSize;
// dst容量不足,倍乘扩容
if (expectedCapacity > dst.elements.length) {
final int actualCapacity = dst.increaseCapacity(expectedCapacity);
srcEnd = min(srcStart + actualCapacity - dstSize, srcEnd);
}
// 移动DefaultHandle到dst的elements中
if (srcStart != srcEnd) {
final DefaultHandle[] srcElems = head.elements;
final DefaultHandle[] dstElems = dst.elements;
int newDstSize = dstSize;
for (int i = srcStart; i < srcEnd; i++) {
DefaultHandle<?> element = srcElems[i];
if (element.recycleId == 0) {
element.recycleId = element.lastRecycledId;
} else if (element.recycleId != element.lastRecycledId) {
throw new IllegalStateException("recycled already");
}
srcElems[i] = null;
// 可能触发dst Stack的丢弃策略
if (dst.dropHandle(element)) {
// Drop the object.
continue;
}
element.stack = dst;
dstElems[newDstSize ++] = element;
}
if (srcEnd == LINK_CAPACITY && head.next != null) {
this.head.relink(head.next);
}
head.readIndex = srcEnd;
if (dst.size == newDstSize) {
return false;
}
dst.size = newDstSize;
return true;
} else {
return false;
}
}
总结
-
如何使用Netty对象池,实现对象的创建和回收?
-
需要有一个构造方法,方法入参包含ObjectPool.Handle
private Item(ObjectPool.Handle<Item> handle) { this.handle = handle; } -
需要有一个对象池ObjectPool,使用Netty提供的ObjectPool.ObjectCreator,实现newObject方法,通过上面的构造方法创建需要池化的对象。
private static final ObjectPool<Item> pool = ObjectPool.newPool(new ObjectPool.ObjectCreator<Item>() { @Override public Item newObject(ObjectPool.Handle<Item> handle) { return new Item(handle); } }); -
为目标池化对象提供recycle方法,负责通过ObjectPool.Handle回收当前实例。
public void recycle() { this.handle.recycle(this); }
-
-
Netty如何抽象对象池?
- ObjectPool:对象池,提供get方法获取对象。
- ObjectCreator:对象创建器,提供newObject方法创建对象。
- Handle:对象回收器,提供recycle方法回收对象。
-
Netty如何实现对象池?
- RecyclerObjectPool实现ObjectPool提供获取对象方法;由用户实现ObjectCreator对象创建逻辑;Recycler.DefaultHandle实现对象回收。
- Recycler是对象池的入口类,每个ObjectPool持有一个Recycler。
private static final class RecyclerObjectPool<T> extends ObjectPool<T> { private final Recycler<T> recycler; RecyclerObjectPool(final ObjectCreator<T> creator) { recycler = new Recycler<T>() { @Override protected T newObject(Handle<T> handle) { return creator.newObject(handle); } }; } @Override public T get() { return recycler.get(); } }- 线程池化,每个线程持有一个Stack对象池,减少资源竞争,由Recycler统一管理。
// Recycler private final FastThreadLocal<Stack<T>> threadLocal = ...;
-
如何处理同一个对象在不同线程创建和回收的场景?
- 前提:对于一个对象池RecyclerObjectPool(或Recycler)的一个线程(ThreadLocal)的Stack
- 当前线程创建和回收的对象,直接保存在Stack的elements数组中,每次获取对象也会优先从这里获取
- 当前线程创建,其他线程回收的对象,会保存在Recycler的ThreadLocal类变量中,Map的key是创建这个对象的Stack容器,value存放当前线程帮助创建对象线程回收的对象。每次获取对象时,如果elements数组中取完了,会从其他线程帮助回收的对象里取
// Recycler // 其他线程的stack实例 - 线程帮助其他线程的stack回收的对象放在WeakOrderQueue容器中 private static final FastThreadLocal<Map<Stack<?>, WeakOrderQueue>> DELAYED_RECYCLED = new FastThreadLocal<Map<Stack<?>, WeakOrderQueue>>() { @Override protected Map<Stack<?>, WeakOrderQueue> initialValue() { return new WeakHashMap<Stack<?>, WeakOrderQueue>(); } };