com.github.netty.core.util.Recycler Maven / Gradle / Ivy
The newest version!
package com.github.netty.core.util;
import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.internal.PlatformDependent;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Supplier;
/**
* Collector (can control the number of instances, ensure the stability of instances, no explosion, no explosion, reduce the number of gc)
*
* @author wangzihao
*/
public class Recycler {
public static final LongAdder HIT_COUNT = new LongAdder();
public static final LongAdder MISS_COUNT = new LongAdder();
private static final int DEFAULT_INSTANCE_COUNT = SystemPropertyUtil.getInt("netty-core.recyclerCount", 2);
private static final boolean ENABLE = SystemPropertyUtil.getBoolean("netty-core.recyclerEnable", true);
/**
* All recyclers
*/
private static final List RECYCLER_LIST = new ArrayList<>();
private final int instanceCount;
/**
* The instance queue of the current object
*/
private final FastThreadLocal> queue = new FastThreadLocal>() {
@Override
protected Queue initialValue() throws Exception {
// return new LinkedBlockingQueue<>();
return PlatformDependent.newFixedMpscQueue(instanceCount);
}
};
/**
* New instance factory for the current object
*/
private Supplier supplier;
// private StackTraceElement formStack;
private Thread formThread;
public Recycler(Supplier supplier) {
this(DEFAULT_INSTANCE_COUNT, supplier);
}
public Recycler(int instanceCount, Supplier supplier) {
this.instanceCount = instanceCount;
this.supplier = supplier;
RECYCLER_LIST.add(this);
this.formThread = Thread.currentThread();
// this.formStack = formThread.getStackTrace()[3];
}
/**
* Gets a list of all recyclers
*
* @return List
*/
public static List getRecyclerList() {
return RECYCLER_LIST;
}
public static void main(String[] args) throws InterruptedException {
int count = 10000;
Recycler recycler = new Recycler<>(() -> {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Date();
});
ThreadPoolX threadPool = new ThreadPoolX("Test", 16);
long begin = System.currentTimeMillis();
CountDownLatch latch = new CountDownLatch(count);
for (int i = 0; i < count; i++) {
threadPool.execute(() -> {
Date instance = recycler.getInstance();
recycler.recycleInstance(instance);
latch.countDown();
});
}
latch.await();
long time = System.currentTimeMillis() - begin;
System.out.printf("time = %d/ms, hit = %s/c, mis = %s/c\n", time, Recycler.HIT_COUNT, Recycler.MISS_COUNT);
}
/**
* Get an instance
*
* @return object
*/
public T getInstance() {
if (ENABLE) {
T value = queue.get().poll();
if (value == null) {
value = supplier.get();
MISS_COUNT.increment();
} else {
HIT_COUNT.increment();
}
return value;
} else {
return supplier.get();
}
}
/**
* Recycling instance
*
* @param value value
*/
public void recycleInstance(T value) {
queue.get().offer(value);
}
@Override
public String toString() {
return "Recycler{" +
"size=" + queue.get().size() +
// ", formStack=" + StringUtil.simpleClassName(formStack.getClassName()) +
", formThread=" + formThread +
'}';
}
}