Class ConcurrentBag<T>

  • Type Parameters:
    T - the templated type to store in the bag
    All Implemented Interfaces:
    java.lang.AutoCloseable

    public class ConcurrentBag<T>
    extends java.lang.Object
    implements java.lang.AutoCloseable
    This is a specialized concurrent bag that achieves superior performance to LinkedBlockingQueue and LinkedTransferQueue for the purposes of a connection pool. It uses ThreadLocal storage when possible to avoid locks, but resorts to scanning a common collection if there are no available items in the ThreadLocal list. Not-in-use items in the ThreadLocal lists can be "stolen" when the borrowing thread has none of its own. It is a "lock-less" implementation using a specialized AbstractQueuedLongSynchronizer to manage cross-thread signaling.

    Note that items that are "borrowed" from the bag are not actually removed from any collection, so garbage collection will not occur even if the reference is abandoned. Thus care must be taken to "requite" borrowed objects otherwise a memory leak will result. Only the "remove" method can completely remove an object from the bag.

    Author:
    Brett Wooldridge, Lijun Liao (xipki)
    • Constructor Summary

      Constructors 
      Constructor Description
      ConcurrentBag()
      Construct a ConcurrentBag with the specified listener.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void add​(ConcurrentBag.BagEntry<T> bagEntry)
      Add a new object to the bag for others to borrow.
      ConcurrentBag.BagEntry<T> borrow​(long timeout, java.util.concurrent.TimeUnit timeUnit)
      The method will borrow a BagEntry from the bag, blocking for the specified timeout if none are available.
      void close()
      Close the bag to further adds.
      boolean remove​(ConcurrentBag.BagEntry<T> bagEntry)
      Remove a value from the bag.
      void requite​(ConcurrentBag.BagEntry<T> bagEntry)
      This method will return a borrowed object to the bag.
      int size()
      Get the total number of items in the bag.
      java.util.List<ConcurrentBag.BagEntry<T>> values()
      This method provides a "snapshot" in time of the bag items.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • ConcurrentBag

        public ConcurrentBag()
        Construct a ConcurrentBag with the specified listener.
    • Method Detail

      • borrow

        public ConcurrentBag.BagEntry<T> borrow​(long timeout,
                                                java.util.concurrent.TimeUnit timeUnit)
                                         throws java.lang.InterruptedException
        The method will borrow a BagEntry from the bag, blocking for the specified timeout if none are available.
        Parameters:
        timeout - how long to wait before giving up, in units of unit
        timeUnit - a TimeUnit determining how to interpret the timeout parameter
        Returns:
        a borrowed instance from the bag or null if a timeout occurs
        Throws:
        java.lang.InterruptedException - if interrupted while waiting
      • requite

        public void requite​(ConcurrentBag.BagEntry<T> bagEntry)
        This method will return a borrowed object to the bag. Objects that are borrowed from the bag but never "requited" will result in a memory leak.
        Parameters:
        bagEntry - the value to return to the bag
        Throws:
        java.lang.NullPointerException - if value is null
        java.lang.IllegalStateException - if the bagEntry was not borrowed from the bag
      • add

        public void add​(ConcurrentBag.BagEntry<T> bagEntry)
        Add a new object to the bag for others to borrow.
        Parameters:
        bagEntry - an object to add to the bag
      • remove

        public boolean remove​(ConcurrentBag.BagEntry<T> bagEntry)
        Remove a value from the bag. This method should only be called with objects obtained by borrow(long, TimeUnit) or reserve(T)
        Parameters:
        bagEntry - the value to remove
        Returns:
        true if the entry was removed, false otherwise
        Throws:
        java.lang.IllegalStateException - if an attempt is made to remove an object from the bag that was not borrowed or reserved first
      • close

        public void close()
        Close the bag to further adds.
        Specified by:
        close in interface java.lang.AutoCloseable
      • values

        public java.util.List<ConcurrentBag.BagEntry<T>> values()
        This method provides a "snapshot" in time of the bag items. It does not "lock" or reserve items in any way. Call reserve(T) on items in the list, or understand the concurrency implications of modifying items, before performing any action on them.
        Returns:
        a possibly empty list of (all) bag items
      • size

        public int size()
        Get the total number of items in the bag.
        Returns:
        the number of items in the bag