Hi Kim, I think there may be an issue with your test. Specifically, this code is suspect:
// Wait for the producer thread to enter BLOCKED state // This ensures that the thread is waiting on the full queue while (thread.getState() == State.RUNNABLE || thread.getState() == State.NEW); I don't think that actually guarantees that the thread is blocked in put(). I was able to reproduce the bug using ArrayBlockingQueue(), but could no longer reproduce it after I changed the above code to this: // Wait for the producer thread to block in queue.put() // This ensures that the thread is waiting on the full queue while (!queue.isPutting(thread)); after also making this change to ArrayBlockingQueue.java: --- a/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -365,10 +365,31 @@ public void put(E e) throws InterruptedException { Objects.requireNonNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); + final boolean added = puttingThreads.add(Thread.currentThread()); try { while (count == items.length) notFull.await(); enqueue(e); + } finally { + if (added) + puttingThreads.remove(Thread.currentThread()); + lock.unlock(); + } + } + + private final java.util.HashSet<Thread> puttingThreads = new java.util.HashSet<>(); + + /** + * Test for putting thread. + * + * @param thread thread to test + * @return true if thread is a putting thread + */ + public boolean isPutting(Thread thread) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return puttingThreads.contains(thread); } finally { lock.unlock(); } So the original test may not be correct due to Java memory model subtleties, etc. -Archie -- Archie L. Cobbs