How would you implement a thread-safe bounded blocking queue from scratch?
A clean implementation uses a single ReentrantLock paired with two separate Condition objects, one called notFull for producer threads and one called notEmpty for consumer threads, along with an internal array, a put index, a take index, and a count of current elements. The put() method acquires the lock, then loops with while (count == capacity) notFull.await() to block while the queue is full, adds the new item once space is available, increments the count, calls notEmpty.signal() to wake a waiting consumer, and releases the lock. The take() method mirrors this: it acquires the lock, loops with while (count == 0) notEmpty.await() to block while the queue is empty, removes an item, decrements the count, calls notFull.signal() to wake a waiting producer, and releases the lock. The key correctness details are using a while loop rather than an if for the condition checks, using the narrower signal() rather than signalAll() since the two separate Condition objects already guarantee the right kind of waiting thread is woken, and always releasing the lock inside a finally block. This is essentially how the JDK's own ArrayBlockingQueue is implemented internally.
Ready to master this question?
Generate a complete walkthrough — background, the full answer in plain language, a working code example explained line by line, a real-world scenario, common mistakes, and how this same question gets asked in different ways.
Sign in to generate a response