
shz.cache.ObjectPool Maven / Gradle / Ivy
package shz.cache;
import shz.linked.ConcurrentLDNode;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public final class ObjectPool extends LocalCache {
private final Supplier> supplier;
private final Consumer closeFun;
private final int capacity, maxIdle;
private final AtomicInteger size;
private final AtomicInteger idle;
private final ConcurrentLDNode> head, tail;
public ObjectPool(Supplier supplier, Consumer closeFun, int capacity, int maxIdle, RefType refType, ReferenceQueue super E> queue) {
super(refType, queue);
this.supplier = () -> getReference(supplier.get());
this.closeFun = closeFun;
this.capacity = capacity;
this.maxIdle = maxIdle;
size = new AtomicInteger(maxIdle);
idle = new AtomicInteger(maxIdle);
head = tail = ConcurrentLDNode.of(null);
head.next(tail);
tail.prev(head);
for (int i = 0; i < maxIdle; ++i) head.addNext(ConcurrentLDNode.of(this.supplier.get()));
}
public ObjectPool(Supplier supplier, int maxIdle, RefType refType, ReferenceQueue super E> queue) {
this(supplier, e -> e = null, Integer.MAX_VALUE, maxIdle, refType, queue);
}
public ObjectPool(Supplier supplier, int maxIdle) {
this(supplier, maxIdle, RefType.SOFT, null);
}
public ObjectPool(Supplier supplier) {
this(supplier, 64);
}
public T apply(Function func) {
E e = get();
T t;
try {
t = func.apply(e);
} finally {
release(e);
}
return t;
}
public E get() {
ConcurrentLDNode> node;
if ((node = head.next()) == tail) return get0(create());
while (!poll(node)) {
sleep();
if ((node = head.next()) == tail) return get0(create());
}
idle.decrementAndGet();
if (node.val == null || node.val.isEnqueued()) {
size.decrementAndGet();
if (node.val != null) closeFun.accept(node.val.get());
return get0(create());
}
return node.val.get();
}
private E get0(ConcurrentLDNode> node) {
if (node == null) return null;
return node.val.get();
}
private ConcurrentLDNode> create() {
if (size.get() >= capacity) return null;
synchronized (this) {
if (size.get() >= capacity) return null;
size.incrementAndGet();
return ConcurrentLDNode.of(supplier.get());
}
}
public void release(E e) {
if (idle.get() < maxIdle) {
//高并发时idle可能超过maxIdle,但无害,不值得去加锁
idle.incrementAndGet();
head.addNext(ConcurrentLDNode.of(getReference(e)));
} else size.decrementAndGet();
}
boolean poll(ConcurrentLDNode> node) {
ConcurrentLDNode> prev = node.prev();
ConcurrentLDNode> next = node.next();
if (!prev.casNext(node, next)) return false;
else next.prev(prev);
return true;
}
void sleep() {
try {
TimeUnit.MICROSECONDS.sleep(500L);
} catch (InterruptedException ignored) {
}
}
public void accept(Consumer consumer) {
apply(t -> {
consumer.accept(t);
return null;
});
}
@Override
public int size() {
return size.get();
}
@Override
public void clear() {
for (ConcurrentLDNode> next = head.next(); next != tail; next = next.next())
if (next.val != null) closeFun.accept(next.val.get());
head.next(tail);
tail.prev(head);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy