A bounded blocking queue is filled past its capacity. What does this print?
```java
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws Exception {
BlockingQueue<Integer> q = new ArrayBlockingQueue<>(2);
boolean a = q.offer(1);
boolean b = q.offer(2);
boolean c = q.offer(3);
Integer head = q.poll();
q.put(4);
System.out.println(a + " " + b + " " + c + " " + head + " " + q);
}
}
```
A. true true false 1 [2, 4]Correct answer
Capacity is fixed at 2, so offer(1) and offer(2) return true while offer(3) finds it full and returns false (silently dropping 3) rather than blocking or throwing; poll() removes the FIFO head 1, put(4) appends into the free slot, and the queue prints head-to-tail as [2, 4] — true true false 1 [2, 4].
B. true true true 1 [2, 3, 4]
Treats an ArrayBlockingQueue like an ArrayList that grows on demand; the capacity passed to the constructor is a hard bound, not an initial size hint, so offer(3) cannot succeed and 3 is not retained.
C. The program throws IllegalStateException: Queue full
This is the behaviour of add(3), not offer(3); add is the Collection-inherited method that throws IllegalStateException on a full queue, whereas offer reports failure by returning false.
D. true true false 3 [2, 4]
Gets the insertion behaviour right but polls from the wrong end, treating the queue as a stack; poll() retrieves and removes the head — the oldest element, 1 — not the most recent.
Explanation
Trace: the queue's capacity is fixed at 2 by the constructor. `offer(1)` and `offer(2)` fill it and return `true`. `offer(3)` finds it full and — this is the contract of `offer` — reports failure by returning `false` rather than blocking or throwing, so 3 is silently dropped. `poll()` removes the *head*, and the queue is FIFO, so it returns `1` and leaves one free slot. `put(4)` would block if the queue were full, but it is not, so 4 is appended immediately. The queue's toString prints head-to-tail: `[2, 4]`. Output: `true true false 1 [2, 4]`.
Why the others are wrong:
`true true true 1 [2, 3, 4]` treats an ArrayBlockingQueue like an ArrayList that grows on demand; the capacity passed to the constructor is a hard bound, not an initial size hint.
`true true false 3 [2, 4]` gets the insertion behaviour right but polls from the wrong end — it treats the queue as a stack. `poll()` retrieves and removes the head, i.e. the oldest element.
`The program throws IllegalStateException: Queue full` is the behaviour of `add(3)`, not `offer(3)`. Confusing the two is the whole point of the question: `add` is the Collection-inherited method that must throw on failure.
Exam tip: BlockingQueue offers three insertion styles for the full-queue case and three removal styles for the empty-queue case. Insert: `add` throws IllegalStateException, `offer` returns false, `put` blocks (and `offer(e, timeout, unit)` blocks then returns false). Remove: `remove` throws NoSuchElementException, `poll` returns null, `take` blocks. The reverse trap is `poll()` on an empty queue — it returns `null`, it does not throw, so it will NPE on you later when you unbox it into an `int`.