Search code examples
javaapache-commonsjava.util.concurrent

Any alternatives for linkedtransfer queue with size restrictions in java 7/8?


To implement producer/consumer pattern, I have used LinkedTransferQueue.

check the below code

while (true) {

    String tmp = new randomString();
    if (linkedTransferQueueString.size() < 10000) {
        linkedTransferQueueString.add(tmp);             
        }

}

From the docs, it states the size is O(n) operation :(. So for adding an element, it should go through the whole collection.

Is there any other concurrent collection queue which has size restriction? Could not find any in java standard collections, apache concurrent collections ?


Solution

  • BlockingQueue is

    BlockingQueue implementations are thread-safe

    [...]

    A BlockingQueue may be capacity bounded.

    and an ArrayBlockingQueue is

    A bounded blocking queue backed by an array

    Here's how you would write your example with it:

    BlockingQueue queue = new ArrayBlockingQueue<>(10000);
    while (true) {
        String tmp = new randomString();
        if (!queue.offer(tmp)) {
            // the limit was reached, item was not added
        }
    }
    

    Or for a simple producer/consumer example

    public static void main(String[] args) {
        // using a low limit so it doesn't take too long for the queue to fill
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
    
        Runnable producer = () -> {
            if (!queue.offer(randomString())) {
                System.out.println("queue was full!");
            }
        };
        Runnable consumer = () -> {
            try {
                queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
        // produce faster than consume so the queue becomes full eventually
        executor.scheduleAtFixedRate(producer, 0, 100, TimeUnit.MILLISECONDS);
        executor.scheduleAtFixedRate(consumer, 0, 200, TimeUnit.MILLISECONDS);
    }