Table of Contents(中文说明)
A lite fast object pool written by Java.
jdk 1.8+
maven-3.3.1+(support toolchains)
<dependency>
<groupId>cn.nextop</groupId>
<artifactId>lite-pool</artifactId>
<version>1.0.0-RC3</version>
</dependency>
$mvn clean install -Dmaven.test.skip=true --global-toolchains ./toolchains.xml
Config | Default value | Details |
---|---|---|
minimum | 0 | minimum allowed objects in pool |
maximum | 16 | maximum allowed objects in pool |
tti | 15 minutes | time to idle, optional maximum pool objects' idle time, unit ms |
ttl | 60 minutes | time to live, optional maximum pool objects' life time, unit ms |
tenancy | 1 minutes | optional leak detection timeout, unit ms, (MUST >= interval ) |
timeout | 8 seconds | default acquire timeout, unit ms |
interval | 15 seconds | default house keeping scheduler's interval, unit ms |
local | true | use ThreadAllocator as L1 cache or not |
verbose | false | print log or not |
fifo | false | pool allocation policy, false has better performance |
allocator | DefaultAllocator | pool allocator, can be customized by extending AbstractAllocator |
supplier | required callback for creating pool objects | |
consumer | optional callback for destroying pool objects | |
validator | optional callback for validating pool objects | |
validation | PULSE | precondition for validator , e.g : new PoolValidation((byte)(PULSE|ACQUIRE|RELEASE)) |
public class YourPoolObject {
}
Pool<YourPoolObject> pool = new PoolBuilder<YourPoolObject>()
.local(true) // using thread local
.supplier(() -> new YourPoolObject())
.interval(interval)
.minimum(minimum)
.maximum(maximum)
.timeout(timeout)
.ttl(ttl)
.tti(tti)
.verbose(true)
...
.build("object pool");
pool.start();
try {
for(int i = 0; i < 1000; i++) {
YourPoolObject object = null;
try {
object = pool.acquire();
if (object != null) {
// your code goes here.
}
} finally {
if (object != null) pool.release(object);
}
}
} finally {
pool.stop();
}
public class YourPoolObject {
}
package your.package;
public class Factory implements Supplier<YourPoolObject> {
@Override
public YourPoolObject get() {
return new YourPoolObject();
}
}
Spring configuration:
<bean id="your.object.pool" class="cn.nextop.lite.pool.impl.ObjectPool"
init-method="start" destroy-method="stop">
<constructor-arg index="0" value="your.object.pool"/>
<property name="config">
<bean class="cn.nextop.lite.pool.PoolConfig">
<property name="minimum" value="10"/>
...
<property name="supplier">
<bean class="your.package.Factory"/>
</property>
</bean>
</property>
</bean>
Pool<YourPoolObject> pool = new PoolBuilder<YourPoolObject>()
.local(true) // using thread local
.supplier(() -> new YourPoolObject())
...
.build("object pool");
pool.addListener(event -> {
YourPoolObject item = event.getItem();
switch (event.getType()) {
case ACQUIRE:
// your code goes here
break;
case RELEASE:
// your code goes here
break;
case LEAKAGE:
// your code goes here
break;
default:
throw new AssertionError();
}
});
pool.start();
public class YourPoolAllocator<T> extends AbstractAllocator<T> {
public YourPoolAllocator(Pool<T> pool, String name) {
super(pool, name);
}
@Override
protected Slot<T> doRelease(T t) {
// if uses thread local as L1 cache, thread allocator will try to acquire without delegating to
// parent allocator, but always delegate to parent to release. that requires your allocator is
// able to remove duplication on release.
//
// if pool object is invalidated, your allocator should delete it and invoke super.consume(t).
//
// please refer to DefaultAllocator and AllocationQueue for more details.
return null;
}
@Override
protected Slot<T> doAcquire(long timeout, TimeUnit unit) {
// returns null if timeout or thread is interrupted.
// if the acquired object is invalid and do not reach out timeout, do following steps:
// step1 : permanently delete it and invoke super.consume(t).
// step2 : acquire again until timeout.
//
// please refer to DefaultAllocator and AllocationQueue for more details.
return null;
}
public static class Factory<T> implements PoolAllocatorFactory<T> {
@Override public final PoolAllocator<T> create(final Pool<T> v) {
String n = v.getName() + ".allocator.your.name"; return new YourPoolAllocator<>(v, n);
}
}
}
Register YourPoolAllocator
to Pool
Pool<YourPoolObject> pool = new PoolBuilder<YourPoolObject>()
.allocator(new YourPoolAllocator.Factory<>())
...
.build("object pool");
MXBean : cn.nextop.lite.pool:type=PoolConfig
Attribute | Modifiable | Details |
---|---|---|
Maximum | Yes | see 2.1. PoolBuilder |
Minimum | Yes | see 2.1. PoolBuilder |
Tenancy | Yes | see 2.1. PoolBuilder |
Timeout | Yes | see 2.1. PoolBuilder |
Tti | Yes | see 2.1. PoolBuilder |
Ttl | Yes | see 2.1. PoolBuilder |
Verbose | Yes | see 2.1. PoolBuilder |
MXBean : cn.nextop.lite.pool:type=PoolAllocator
Attribute | Modifiable | Details |
---|---|---|
EntireCount | No | pool's entire object count. |
WorkingCount | No | pool's working object count, equivalent to EntireCount - RestingCount . |
RestingCount | No | pool's resting object count. |
PendingCount | No | pool's pending request count. |
Test env:
OS : Windows 7 Home(64bit)
CPU: Intel(R) Core(TM) i3-4710 CPU @ 3.70GHz 3.70GHz
RAM: 8.00 GB
JDK: java version "1.8.0_151"
Test case:
Basic Parameters: 10 minimum, 10 maximum
TestObject object = pool.acquire();
if (object != null) pool.release(object);
(unit: ops/ms)
Parameters: see BaseTest.java
Benchmark Classes: see LitePoolBenchmark.java and CommonsPool2Benchmark.java
Run Benchmark.java
Use ThreadAllocator
as L1 cache result:
Unused ThreadAllocator
as L1 cache result: