Class BeanPool<T>
- Type Parameters:
T
- The type of the bean that being pooled.
An object pool for beans that are both expensive to construct and not thread safe.
The pool vends them temporarily to threads that need them when they call checkOut()
.
This pool is designed to work well with virtual threads, by avoiding thread locals or any
assumptions about how many distinct threads will request objects. If all the beans are currently
checked out and a new bean is requested it will be created using the factory provided to the
constructor. Therefore the number of beans created and available in the pool should grow to match
the general rate of contention, rather than how many threads are in use.
Beans in the pool can be atomically cleared and closed (if they implement Closeable
).
Any beans checked out when clear()
is called will remain untouched, but when they are
checked back in they will be closed and discarded at that point.
Note: this pool doesn't release objects in the background. If you have a sudden spike of traffic that drives many checkouts, memory usage may grow significantly and not be released. Fixing this would be a good future improvement to the pool.
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic interface
A handle to a pooled object. -
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionvoid
checkIn
(BeanPool.Handle<T> handle) Puts a context back into the pool.checkOut()
Returns a cached bean or creates a new one.void
clear()
Empties the pool.<R,
E extends Throwable>
RuseContext
(io.micronaut.core.util.functional.ThrowingFunction<BeanPool.Handle<T>, R, E> block) Runs the block with a handle checked out, checking it back in again at the end even if an exception is thrown.
-
Constructor Details
-
BeanPool
Constructs an object pool that uses the given factory to create new entries.- Parameters:
factory
- Used to create new entries when the pool is empty. Must be thread safe.
-
-
Method Details
-
checkOut
Returns a cached bean or creates a new one. CallSupplier.get()
to obtain the underlying object.- Returns:
- a wrapper for the entry that you should pass to
checkIn(Handle)
when you're done with it to put it back into the pool.
-
checkIn
Puts a context back into the pool. It should be returned in a 'clean' state, so whatever thread picks it up next finds it ready to use and without any leftover data from prior usages. If the pool has beencleared
previously, and the pooled object isCloseable
, then the object will be closed at this point (exceptions are ignored).- Parameters:
handle
- The object you got fromcheckOut()
.
-
useContext
public <R,E extends Throwable> R useContext(io.micronaut.core.util.functional.ThrowingFunction<BeanPool.Handle<T>, R, throws EE> block) Runs the block with a handle checked out, checking it back in again at the end even if an exception is thrown.This is implemented equivalently to:
try (Handle<T> handle = checkOut()) { return block.apply(handle); }
- Type Parameters:
R
- Return type of the block.E
- What type of exception the block can throw.- Parameters:
block
- The lambda that will be executed with the checked out handle.- Returns:
- the same object returned by the block.
- Throws:
E
- if thrown byblock
.
-
clear
public void clear()Empties the pool. Beans currently checked out withcheckOut()
will not be re-added to the pool whencheckIn(Handle)
is called, and may be closed if they areCloseable
. Likewise, all beans in the pool are closed if they areCloseable
and exceptions thrown byCloseable.close()
are ignored.
-