Class BeanPool<T>

java.lang.Object
io.micronaut.views.react.util.BeanPool<T>
Type Parameters:
T - The type of the bean that being pooled.

@Internal public class BeanPool<T> extends Object

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.

  • Constructor Details

    • BeanPool

      public BeanPool(Supplier<T> factory)
      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

      public BeanPool.Handle<T> checkOut()
      Returns a cached bean or creates a new one. Call Supplier.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

      public void checkIn(BeanPool.Handle<T> handle)
      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 been cleared previously, and the pooled object is Closeable, then the object will be closed at this point (exceptions are ignored).
      Parameters:
      handle - The object you got from checkOut().
    • useContext

      public <R, E extends Throwable> R useContext(io.micronaut.core.util.functional.ThrowingFunction<BeanPool.Handle<T>,R,E> block) throws E
      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 by block.
    • clear

      public void clear()
      Empties the pool. Beans currently checked out with checkOut() will not be re-added to the pool when checkIn(Handle) is called, and may be closed if they are Closeable. Likewise, all beans in the pool are closed if they are Closeable and exceptions thrown by Closeable.close() are ignored.