- Type Parameters:
T- the type ofPoolablecontained in the pool, as determined by the configured allocator.
- All Superinterfaces:
PoolTap<T>
- All Known Implementing Classes:
BlazePool
Pools are thread-safe, and their PoolTap.claim(Timeout) methods can be
called concurrently from multiple threads.
This is a strictly stronger guarantee than PoolTap provides.
Pools extend the PoolTap class, which provides the API for accessing
the objects contained in the pool.
Pools contain Poolable objects. When you claim an object in a pool,
you also take upon yourself the responsibility of eventually
releasing that object again. By far the most
common idiom to achieve this is with a try-finally clause:
Timeout timeout = new Timeout(1, SECONDS);
MyPoolable obj = pool.claim(timeout);
try {
// Do useful things with 'obj'.
// Note that 'obj' will be 'null' if 'claim' timed out.
} finally {
if (obj != null) {
obj.release();
}
}
The pools are resizable, and can have their capacity changed at any time after they have been created.
All pools are configured with a certain size, the number of objects that the
pool will have allocated at any one time, and they can change this number on
the fly using the setTargetSize(long) method. The change does not
take effect immediately, but instead moves the "goal post" and leaves the
pool to move towards it at its own pace.
No guarantees can be made about when the pool will actually reach the target size, because it might depend on how long it takes for a certain number of objects to be released back into the pool.
| NOTE |
Pools created with of(Object[]) are not resizable, and calling
setTargetSize(long) or ManagedPool.setTargetSize(long) will
cause an UnsupportedOperationException to be thrown.
|
|---|
shut down
when they are no longer needed.
Note that Pools don't override the deprecated Object.finalize() method.
Pools are expected to rely on explicit clean-up for releasing their resources.
- Author:
- Chris Vest
- See Also:
-
Method Summary
Modifier and TypeMethodDescriptionstatic <T extends Poolable>
PoolBuilder<T> Get aPoolBuilderbased on the givenAllocatororReallocator, which can then in turn be used to build aPoolinstance with the desired configuration.static <T extends Poolable>
PoolBuilder<T> fromInline(Allocator<T> allocator) Get aPoolBuilderbased on the givenAllocatororReallocator, which can then in turn be used to build aPooloperating in the inline mode, with the desired configuration.static <T extends Poolable>
PoolBuilder<T> fromThreaded(Allocator<T> allocator) Get aPoolBuilderbased on the givenAllocatororReallocator, which can then in turn be used to build a threadedPoolinstance with the desired configuration.Get theManagedPoolinstance that represents this pool.Get aPoolTapthat only support access by one thread at a time.longGet the currently configured target size of the pool.Get a thread-safePoolTapimplementation for this pool, which can be freely shared among multiple threads.Get a thread-safePoolTapimplementation for this pool, which can be freely shared among multiple threads, including virtual threads.of(T... objects) Build aPoolinstance that pools the given set of objects.voidsetTargetSize(long size) Set the target size for this pool.shutdown()Initiate the shutdown process on this pool, and return aCompletioninstance representing the shutdown procedure.switchAllocator(Allocator<T> replacementAllocator) Initiate a switch from the current allocator to the given allocator.
-
Method Details
-
from
Get aPoolBuilderbased on the givenAllocatororReallocator, which can then in turn be used to build aPoolinstance with the desired configuration.This method is synonymous for
fromThreaded(Allocator).- Type Parameters:
T- The type ofPoolablethat is created by the allocator, and the type of objects that the configured pools will contain.- Parameters:
allocator- The allocator we want our pools to use. This cannot benull.- Returns:
- A
PoolBuilderthat admits additional configurations, before the pool instance is built. - See Also:
-
fromThreaded
Get aPoolBuilderbased on the givenAllocatororReallocator, which can then in turn be used to build a threadedPoolinstance with the desired configuration.The returned
PoolBuilderwill build pools that allocate and deallocate objects in a background thread. Hence, the "threaded" in the name; the objects are created and destroyed by the background thread, out of band with the threads that call into the pool to claim objects.By moving the allocation of objects to a background thread, it can be guaranteed that the timeouts given to
claimwill always be honoured. In other words, a slow allocation cannot block aclaimcall beyond its intended timeout.- Type Parameters:
T- The type ofPoolablethat is created by the allocator, and the type of objects that the configured pools will contain.- Parameters:
allocator- The allocator we want our pools to use. This cannot benull.- Returns:
- A
PoolBuilderthat admits additional configurations, before the pool instance is built.
-
fromInline
Get aPoolBuilderbased on the givenAllocatororReallocator, which can then in turn be used to build aPooloperating in the inline mode, with the desired configuration.The returned
PoolBuilderwill build pools that allocate and deallocate objects in-line with, and as part of, the claim calls. Hence, the "inline" in the name.This way, pools operating in the inline mode do not need a background thread. This means that it is harder for claim to honour the given
Timeout. It also means that the background services, such as background expiration checking, and automatically replacing failed allocations, are not available. On the other hand, inline pool consumes fewer memory and CPU resources.- Type Parameters:
T- The type ofPoolablethat is created by the allocator, and the type of objects that the configured pools will contain.- Parameters:
allocator- The allcoator we want our pools to use. This cannot benull.- Returns:
- A
PoolBuilderthat admits additional configurations, before the pool instance is built.
-
of
Build aPoolinstance that pools the given set of objects.The objects in the pool are never expired, and never deallocated. Explicitly expired objects simply return to the pool.
This means that the returned pool has no background allocation thread, and has no expiration checking overhead when claiming objects.
The given objects are wrapped in
Pooledobjects, which implement thePoolableinterface.Shutting down the returned pool will not cause the given objects to be deallocated. The shutdown process will complete as soon as the last claimed object is released back to the pool.
Note NOTE Passing duplicate objects to this method is not supported. The behaviour of the pool is unspecified if there are duplicates among the objects passed as arguments to this method. - Type Parameters:
T- The type of objects being pooled.- Parameters:
objects- The objects the pool should contain.- Returns:
- A pool of the given objects.
-
shutdown
Completion shutdown()Initiate the shutdown process on this pool, and return aCompletioninstance representing the shutdown procedure.The shutdown process is asynchronous, and the shutdown method is guaranteed to not wait for any claimed
Poolablesto be released.The shutdown process cannot complete before all Poolables are released back into the pool and
deallocated, and all internal resources (such as threads, for instance) have been released as well. Only when all of these things have been taken care of, does the await methods of the Completion return.Once the shutdown process has been initiated, that is, as soon as this method is called, the pool can no longer be used and all calls to
PoolTap.claim(Timeout)will throw anIllegalStateException. Threads that are already waiting for objects in the claim method, will also wake up and receive anIllegalStateException.All objects that are already claimed when this method is called, will continue to function until they are
released.The shutdown process is guaranteed to never deallocate objects that are currently claimed. Their deallocation will wait until they are released.
- Returns:
- A
Completioninstance that represents the shutdown process.
-
switchAllocator
Initiate a switch from the current allocator to the given allocator.This will cause all current objects to be deallocated by the old allocator, and reallocated by the new allocator. The objects will be replaced one at a time.
The returned completion will complete when all objects have been replaced, or if the pool shuts down. If another switch is initiated before the completion of a prior switch, then the prior completion will complete when there are no more objects left from the allocator that was current at the time the prior completion was initiated.
Direct pools, created with the
of(Object[])method, do not support switching allocators, and will instead throw anUnsupportedOperationExceptionfrom this method.If this pool has already been shut down, then this method immediately returns a completed completion instance.
- Parameters:
replacementAllocator- The new allocator.- Returns:
- A
Completioninstance that represents the switch process. - Throws:
UnsupportedOperationException- If this pool contain only contain pre-allocated objects.
-
setTargetSize
void setTargetSize(long size) Set the target size for this pool. The pool will strive to keep this many objects allocated at any one time.If the new target size is greater than the old one, the pool will allocate more objects until it reaches the target size. If, on the other hand, the new target size is less than the old one, the pool will deallocate more and allocate less, until the new target size is reached.
No guarantees are made about when the pool actually reaches the target size. In fact, it may never happen as the target size can be changed as often as one sees fit.
Pools that do not support a size less than 0 (which would deviate from the standard configuration space) will throw an
IllegalArgumentExceptionif passed -1 or less.Pools that do not support online resizing will throw an
UnsupportedOperationException.- Parameters:
size- The new target size of the pool.- Throws:
UnsupportedOperationException- If this pool cannot be resized.
-
getTargetSize
long getTargetSize()Get the currently configured target size of the pool. Note that this is not the number of objects currently allocated by the pool - only the number of allocations the pool strives to keep alive.- Returns:
- The current target size of this pool.
-
getManagedPool
ManagedPool getManagedPool()Get theManagedPoolinstance that represents this pool.- Returns:
- The
ManagedPoolinstance for this pool.
-
getThreadSafeTap
Get a thread-safePoolTapimplementation for this pool, which can be freely shared among multiple threads.If the pool tap will be accessed by virtual threads, then
getVirtualThreadSafeTap()should be used instead.- Returns:
- A thread-safe
PoolTap.
-
getVirtualThreadSafeTap
Get a thread-safePoolTapimplementation for this pool, which can be freely shared among multiple threads, including virtual threads.The implementation of this
PoolTapavoids the use ofThreadLocalvariables, locking mechanisms, and other API calls that are poorly supported by, or disruptive to, virtual threads.- Returns:
- A thread-safe
PoolTap.
-
getSingleThreadedTap
Get aPoolTapthat only support access by one thread at a time. In other words, wherePoolTap.claim(Timeout)cannot be called concurrently in multiple threads *on the same tap*.The pool itself will still be thread-safe, but each thread that wishes to access the pool via a thread-local tap, must have their own tap instance.
It is a use error to access these pool taps concurrently from multiple threads, or to transfer them from one thread to another without safe publication.
- Returns:
- A thread-local
PoolTap.
-