归档
参考
单元测试
public class ObjPoolTest {
private static final Recycler < User > RECYCLER = new Recycler < User > ( ) {
@Override
protected User newObject ( Handle < User > handle) {
User user = new User ( handle) ;
user. name = "init-" + LocalTime . now ( ) ;
return user;
}
} ;
static final class User {
public String name;
private final Recycler. Handle < User > handle;
public User ( Recycler. Handle < User > handle) {
this . handle = handle;
}
public void recycle ( ) {
handle. recycle ( this ) ;
}
}
@Test
public void test ( ) throws InterruptedException {
User user1 = RECYCLER . get ( ) ;
user1. name = "hello" ;
user1. recycle ( ) ;
Runnable run = ( ) -> {
User user2 = RECYCLER . get ( ) ;
System . out. println ( "\nCur-Thread-Name: " + Thread . currentThread ( ) . getName ( ) ) ;
System . out. println ( user2. name) ;
System . out. println ( user1 == user2) ;
} ;
run. run ( ) ;
Thread thread1 = new Thread ( run, "test-01" ) ;
thread1. start ( ) ;
thread1. join ( ) ;
}
@Test
public void testQueue ( ) {
MpscChunkedArrayQueue < Integer > queue = new MpscChunkedArrayQueue < > ( 2 , 8 ) ;
for ( int i = 0 ; i < 10 ; i++ ) {
queue. relaxedOffer ( i) ;
queue. offer ( i) ;
}
System . out. println ( queue. size ( ) ) ;
queue. forEach ( i -> System . out. println ( "i: " + i) ) ;
}
}
原理
类结构
public abstract class Recycler < T > {
private final int maxCapacityPerThread;
private final int interval;
private final int chunkSize;
private final FastThreadLocal < LocalPool < T > > threadLocal = new FastThreadLocal < LocalPool < T > > ( ) {
@Override
protected LocalPool < T > initialValue ( ) {
return new LocalPool < T > ( maxCapacityPerThread, interval, chunkSize) ;
}
} ;
private static final class LocalPool < T > implements MessagePassingQueue. Consumer < DefaultHandle < T > > {
private final ArrayDeque < DefaultHandle < T > > batch;
private volatile MessagePassingQueue < DefaultHandle < T > > pooledHandles;
private int ratioCounter;
LocalPool ( int maxCapacity, int ratioInterval, int chunkSize) {
batch = new ArrayDeque < DefaultHandle < T > > ( chunkSize) ;
pooledHandles = ( MessagePassingQueue < DefaultHandle < T > > ) newMpscQueue ( chunkSize, maxCapacity) ;
ratioCounter = ratioInterval;
}
}
private static final class DefaultHandle < T > extends EnhancedHandle < T > {
private volatile int state;
private final LocalPool < T > localPool;
private T value;
DefaultHandle ( LocalPool < T > localPool) {
this . localPool = localPool;
}
}
}
调用链
public final T get ( ) {
. . .
LocalPool < T > localPool = threadLocal. get ( ) ;
DefaultHandle < T > handle = localPool. claim ( ) ;
T obj;
if ( handle == null ) {
handle = localPool. newHandle ( ) ;
if ( handle != null ) {
obj = newObject ( handle) ;
handle. set ( obj) ;
} else {
obj = newObject ( ( Handle < T > ) NOOP_HANDLE ) ;
}
} else {
obj = handle. get ( ) ;
}
return obj;
}
io.netty.util.Recycler.LocalPool
DefaultHandle < T > claim ( ) {
MessagePassingQueue < DefaultHandle < T > > handles = pooledHandles;
if ( handles == null ) {
return null ;
}
if ( batch. isEmpty ( ) ) {
handles. drain ( this , chunkSize) ;
}
DefaultHandle < T > handle = batch. pollFirst ( ) ;
if ( null != handle) {
handle. toClaimed ( ) ;
}
return handle;
}
@Override
public void accept ( DefaultHandle < T > e) {
batch. addLast ( e) ;
}
DefaultHandle < T > newHandle ( ) {
if ( ++ ratioCounter >= ratioInterval) {
ratioCounter = 0 ;
return new DefaultHandle < T > ( this ) ;
}
return null ;
}
void release ( DefaultHandle < T > handle, boolean guarded) {
if ( guarded) {
handle. toAvailable ( ) ;
} else {
handle. unguardedToAvailable ( ) ;
}
Thread owner = this . owner;
if ( owner != null && Thread . currentThread ( ) == owner && batch. size ( ) < chunkSize) {
accept ( handle) ;
} else if ( owner != null && isTerminated ( owner) ) {
this . owner = null ;
pooledHandles = null ;
} else {
MessagePassingQueue < DefaultHandle < T > > handles = pooledHandles;
if ( handles != null ) {
handles. relaxedOffer ( handle) ;
}
}
}
io.netty.util.Recycler.DefaultHandle
@Override
public void recycle ( Object object) {
if ( object != value) {
throw new IllegalArgumentException ( "object does not belong to handle" ) ;
}
localPool. release ( this , true ) ;
}
总结
只能在当前线程有用 每 8 次才创建一个句柄加入到对象池 设置有两级缓存,一级缓存默认 32 个,二级缓存默认 4096 个(且最多只缓存前面的 4096 个)