Design Bounded Blocking Queue - Problem

Implement a thread-safe bounded blocking queue that has the following methods:

  • BoundedBlockingQueue(int capacity) - The constructor initializes the queue with a maximum capacity.
  • void enqueue(int element) - Adds an element to the front of the queue. If the queue is full, the calling thread is blocked until the queue is no longer full.
  • int dequeue() - Returns the element at the rear of the queue and removes it. If the queue is empty, the calling thread is blocked until the queue is no longer empty.
  • int size() - Returns the number of elements currently in the queue.

Your implementation will be tested using multiple threads at the same time. Each thread will either be a producer thread that only makes calls to the enqueue method or a consumer thread that only makes calls to the dequeue method. The size method will be called after every test case.

Please do not use built-in implementations of bounded blocking queue as this will not be accepted in an interview.

Input & Output

Example 1 — Basic Queue Operations
$ Input: operations = ["BoundedBlockingQueue","enqueue","dequeue","dequeue","enqueue","enqueue","enqueue","dequeue","size"], values = [2,1,null,null,0,2,3,null,null]
Output: [1,0,2,1]
💡 Note: Create queue capacity 2, enqueue 1, dequeue returns 1, dequeue returns 0 (blocks until 0 enqueued), enqueue 0,2,3 (3 blocks until space), dequeue returns 2, size returns 1
Example 2 — Full Queue Blocking
$ Input: operations = ["BoundedBlockingQueue","enqueue","enqueue","size","dequeue"], values = [1,1,2,null,null]
Output: [1,1]
💡 Note: Create queue capacity 1, enqueue 1 (fills queue), enqueue 2 blocks until space available, size shows 1, dequeue returns 1
Example 3 — Empty Queue Blocking
$ Input: operations = ["BoundedBlockingQueue","dequeue","enqueue","size"], values = [3,null,5,null]
Output: [5,0]
💡 Note: Create queue capacity 3, dequeue blocks until element available (5), enqueue 5 unblocks dequeue which returns 5, size shows 0

Constraints

  • 1 ≤ capacity ≤ 1000
  • 0 ≤ element ≤ 1000
  • At most 1000 calls will be made to enqueue, dequeue, and size

Visualization

Tap to expand
Design Bounded Blocking Queue INPUT Bounded Queue (cap=2) [ ] [ ] Operations: 1. BoundedBlockingQueue(2) 2. enqueue(1) 3. dequeue() 4. dequeue() 5. enqueue(0) 6. enqueue(2) 7. enqueue(3) 8. dequeue() 9. size() Threads: Producer Consumer [2,1,null,null,0,2,3,null,null] ALGORITHM STEPS 1 Initialize with Locks Use mutex + 2 condition vars (notFull, notEmpty) 2 Enqueue Logic If full: wait(notFull) Add elem, signal(notEmpty) 3 Dequeue Logic If empty: wait(notEmpty) Remove elem, signal(notFull) 4 Thread-Safe Size Lock before reading count Condition Variable Flow Producer Queue Consumer wait(notFull) signal(notEmpty) wait(notEmpty) signal(notFull) BLOCKS if needed FINAL RESULT Execution Trace: 1. Init queue cap=2: [] 2. enqueue(1): [1] 3. dequeue() --> returns 1 4. dequeue() --> BLOCKS 5. enqueue(0): [0], unblocks #4 #4 returns 0 6. enqueue(2): [2] 7. enqueue(3): [2,3] 8. dequeue() --> returns 2 9. size() --> returns 2 Final queue: [3] Output: [1, 0, 2, 2] OK - All operations completed Thread-safe blocking verified Key Insight: Condition Variables enable threads to WAIT and be NOTIFIED when queue state changes. Two conditions needed: notFull (for producers) and notEmpty (for consumers). This avoids busy-waiting and ensures thread-safe, efficient blocking queue operations. TutorialsPoint - Design Bounded Blocking Queue | Condition Variables with Blocking
Asked in
Google 45 Amazon 38 Microsoft 32 Facebook 28
23.4K Views
Medium Frequency
~25 min Avg. Time
892 Likes
Ln 1, Col 1
Smart Actions
💡 Explanation
AI Ready
💡 Suggestion Tab to accept Esc to dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen