Thread pool with bounded queue

前端 未结 2 1303
一整个雨季
一整个雨季 2021-02-03 16:17

I have seen the thread pool executor implementation and the rejected execution policies that it provides. However, I have a custom requirement - I want to have a call back mecha

2条回答
  •  傲寒
    傲寒 (楼主)
    2021-02-03 17:01

    So here is the code that I have based on the answer above. The call to saturated and unSaturated needs to be invoked during sustained load on the worker queue of the thread pool and I believe the implementation achieves it by making use of non blocking algorithm.

    Also, this implementation can be used for any implementation of blocking queue (also the original queue could be bounded or unbounded).

    I am using guava's ForwardingBlockingQueue to write my decorator. Any suggestions would be greatly appreciated.

    import java.util.Collection;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicBoolean;
    
    import com.google.common.util.concurrent.ForwardingBlockingQueue;
    
    /**
     * @version $Id$
     * @param  the type of elements held in this blocking queue.
     */
    public class BoundObservableBlockingQueue extends ForwardingBlockingQueue {
    
        /** observer to receive callbacks. */
        private final ISaturatedQueueObserver queueBoundObserver;
    
        /** original blocking queue being decorated. */
        private final BlockingQueue queueDelegate;
    
        /** user specified blocking queue bound capacity. */
        private final int boundCapacity;
    
        /** user specified blocking queue bound capacity. */
        private final int boundThreshold;
    
        /** flag to represent the saturated state of the queue. */
        private final AtomicBoolean isSaturated = new AtomicBoolean(false);
    
    /**
         * 
         * @param pQueue {@link BlockingQueue
         * @param pQueueBoundObserver {@link ISaturatedQueueObserver}
         * @param pBoundCapacity saturation capacity for the bound queue.
         */
        public BoundObservableBlockingQueue(final BlockingQueue pQueue,
                final ISaturatedQueueObserver pQueueBoundObserver, final int pBoundCapacity) {
            queueDelegate = pQueue;
            queueBoundObserver = pQueueBoundObserver;
            boundCapacity = pBoundCapacity;
            boundThreshold = (int) 0.8 * pBoundCapacity;
        }
    
        /** {@inheritDoc} */
        @Override
        public final boolean offer(final E e) {
            boolean isOffered = delegate().offer(e);
            checkSaturated();
            return isOffered;
        }
    
        /** {@inheritDoc} */
        @Override
        public final boolean offer(final E e, final long timeout, final TimeUnit unit) throws InterruptedException {
            boolean isOffered = delegate().offer(e, timeout, unit);
            checkSaturated();
            return isOffered;
        }
    
        /** {@inheritDoc} */
        @Override
        public final E remove() {
            E element = delegate().remove();
            checkUnsaturated();
            return element;
        }
    
        /** {@inheritDoc} */
        @Override
        public final E poll() {
            E element = delegate().poll();
            checkUnsaturated();
            return element;
        }
    
        /** {@inheritDoc} */
        @Override
        public final E poll(final long timeout, final TimeUnit unit) throws InterruptedException {
            E element = delegate().poll(timeout, unit);
            checkUnsaturated();
            return element;
        }
    
        /** {@inheritDoc} */
        @Override
        public final E take() throws InterruptedException {
            E element = delegate().take();
            checkUnsaturated();
            return element;
        }
    
        /** {@inheritDoc} */
        @Override
        public final boolean remove(final Object o) {
            boolean isRemoved = delegate().remove(o);
            checkUnsaturated();
            return isRemoved;
        }
    
        /** {@inheritDoc} */
        @Override
        protected final BlockingQueue delegate() {
            return queueDelegate;
        }
    
        // thread pool uses this only during invocation of shutdown; in which cases call to unSaturated isn't needed because
        // the queue is no longer ready to accept any more records.
        /** {@inheritDoc} */
        @Override
        public final int drainTo(final Collection c) {
            return delegate().drainTo(c);
        }
    
        private void checkUnsaturated() {
            if (delegate().size() < boundThreshold && isSaturated.get()) {
                if (isSaturated.compareAndSet(true, false)) {
                    queueBoundObserver.onUnsaturated();
                }
            }
        }
    
        private void checkSaturated() {
            if ((delegate().size() >= boundCapacity) && !isSaturated.get()) {
                if (isSaturated.compareAndSet(false, true)) {
                    queueBoundObserver.onSaturated();
                }
            }
        }
    }
    

提交回复
热议问题