BlockingQueue (Java Concurrency)
Thread-safe queue with blocking operations for producer-consumer coordination.
📌 Key Idea
BlockingQueue is a java.util.concurrent interface for safe handoff between producer and consumer threads. put() blocks when full; take() blocks when empty — giving natural backpressure inside one JVM.Problem it solves
- Manual producer-consumer code with
wait()/notify()is error-prone and hard to maintain. - Without bounded handoff, fast producers can overwhelm consumers and cause memory pressure.
BlockingQueueprovides safe coordination and natural in-process backpressure.
Visual
📦 Producer-Consumer with built-in backpressure
Producer threads --put()--> [ BlockingQueue ] --take()--> Consumer threads Queue full -> put() blocks producer Queue empty -> take() blocks consumer No manual wait()/notify() needed.
When to Use
- Producer-consumer pipelines where multiple threads exchange tasks/data.
- You need in-memory backpressure instead of unbounded memory growth.
- You want thread-safe coordination without writing lock/wait-notify code.
When NOT to Use
- You need durable messaging across process restarts (use Kafka/RabbitMQ, etc.).
- Cross-service communication (BlockingQueue is in-process only).
- No clear capacity planning for bounded queues under peak load.
Code Variations
1️⃣ Simple producer-consumerjava
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try { queue.put("Message"); } catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}).start();
new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
String msg = queue.take();
System.out.println("Consumed: " + msg);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}).start();Use interrupt handling instead of swallowing exceptions; this avoids stuck shutdowns.
2️⃣ ThreadPoolExecutor + BlockingQueue (production pattern)java
ThreadPoolExecutor exec = new ThreadPoolExecutor(
8, 16, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(500),
new ThreadPoolExecutor.CallerRunsPolicy()
);Queue + rejection policy controls overload behavior explicitly.
3️⃣ PriorityBlockingQueue for priority jobsjava
record Job(int priority, long seq, Runnable task)
implements Comparable<Job> {
public int compareTo(Job o) {
int p = Integer.compare(o.priority, this.priority); // high first
return p != 0 ? p : Long.compare(this.seq, o.seq); // tie-breaker
}
}
BlockingQueue<Job> q = new PriorityBlockingQueue<>();PriorityBlockingQueue is unbounded by default — add producer throttling or external limits.Pros & Cons
👍 Pros
- Thread-safe out of the box.
- Natural backpressure via blocking semantics.
- Simplifies concurrency by avoiding manual
wait()/notify(). - Works seamlessly with executor-based architectures.
👎 Cons
- Blocking can reduce throughput if capacity and consumer count are poorly tuned.
- In-memory only — no durability on process crash.
- Misused priority/unbounded queues can trigger OOM or starvation.
Common BlockingQueue implementations
| Aspect | Class | Best use | Caveat |
|---|---|---|---|
ArrayBlockingQueue | Bounded FIFO, predictable memory | Fixed capacity; blocks quickly at peak | |
LinkedBlockingQueue | High throughput pipelines | Can grow large if unbounded | |
PriorityBlockingQueue | Priority-based processing | Unbounded + no strict FIFO for same priority unless tie-breaker | |
DelayQueue | Scheduled/deferred tasks | Requires Delayed items; no plain FIFO semantics | |
SynchronousQueue | Direct handoff, zero buffering | Producer/consumer must rendezvous exactly |
Interview Q&A
Likely Follow-up Questions
- Difference between
offer(timeout)andput()for overload handling? - How would you add task deduplication on top of BlockingQueue?
- When do you move from in-JVM queue to Kafka/RabbitMQ?
Quick Cheat Sheet
TypeIn-memory, thread-safe, blocking queue (JVM-local).
Key ops
put() blocks on full, take() blocks on empty.Default pick
ArrayBlockingQueue (bounded) for safer memory control.Production must-haveQueue depth + wait-time metrics + interrupt-safe code.