Collections: BlockingQueue coordinates producer and consumer

put blocks when the queue is full and take blocks when it is empty, so a bounded queue applies back-pressure without any manual locking.

Code
var queue = new ArrayBlockingQueue<Integer>(2);
var results = Collections.synchronizedList(new ArrayList<Integer>());

Thread producer = new Thread(() -> {
    try {
        for (int i = 1; i <= 5; i++) queue.put(i);
        queue.put(-1);                       // poison pill
    } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
});
Thread consumer = new Thread(() -> {
    try {
        int v;
        while ((v = queue.take()) != -1) results.add(v);
    } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
});

producer.start(); consumer.start();
producer.join(); consumer.join();
System.out.println("consumed in order: " + results);
Output
consumed in order: [1, 2, 3, 4, 5]
Advertisement

Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.

Published 2026-07-30