From ExtremeProgrammingChallengeFourteenTheBug ---- This test exposes the error with the message "producer1 blocked". It's verbose and it's slow (takes seconds to execute), and I ''hate'' that it's not deterministic. It can also report false errors if the process doesn't get any CPU time for 200 msec. public void testTwoProducersTwoConsumers() throws Exception { final int numberOfItems = 10000; final Watchdog watchdog = new Watchdog(); final Bounded''''''Buffer buffer = new Bounded''''''Buffer(1); Thread producer1 = new Producer(buffer, watchdog, numberOfItems); Thread producer2 = new Producer(buffer, watchdog, numberOfItems); Thread consumer1 = new Consumer(buffer, watchdog, numberOfItems); Thread consumer2 = new Consumer(buffer, watchdog, numberOfItems); producer1.start(); producer2.start(); consumer1.start(); consumer2.start(); watchdog.waitUntilInactive(); assert("producer1 blocked", !producer1.isAlive()); assert("producer2 blocked", !producer2.isAlive()); assert("consumer1 blocked", !consumer1.isAlive()); assert("consumer2 blocked", !consumer2.isAlive()); } Watchdog is how I detect that nothing is happening. It allows the test to work on faster or slower CPUs: private static class Watchdog { private long msecOfLastReset; public Watchdog() { reset(); } public synchronized void reset() { msecOfLastReset = System.currentTimeMillis(); } public void waitUntilInactive() throws Interrupted''''''Exception { while (msecSinceReset() < 200) Thread.sleep(200); } private synchronized long msecSinceReset() { return System.currentTimeMillis() - msecOfLastReset; } }; The producers and consumers are about what you'd expect (I expect): private abstract static class Actor extends Thread { protected Bounded''''''Buffer buffer; private Watchdog watchdog; private int numberOfItems; public Actor(Bounded''''''Buffer buffer, Watchdog watchdog, int numberOfItems) { this.buffer = buffer; this.watchdog = watchdog; this.numberOfItems = numberOfItems; } public void run() { try { for (int i = 0; i < numberOfItems; i++) { act(); watchdog.reset(); } } catch (Interrupted''''''Exception e) { } } protected abstract void act() throws Interrupted''''''Exception; }; private static class Producer extends Actor { public Producer(Bounded''''''Buffer buffer, Watchdog watchdog, int numberOfItems) { super(buffer, watchdog, number''''''Of''''''Items); } protected void act() throws Interrupted''''''Exception { buffer.put(new Object()); } }; private static class Consumer extends Actor { public Consumer(Bounded''''''Buffer buffer, Watchdog watchdog, int numberOfItems) { super(buffer, watchdog, numberOfItems); } protected void act() throws Interrupted''''''Exception { buffer.take(); } }; I added a new constructor to Bounded''''''Buffer that takes the buffer size, as I wasn't able to reproduce the deadlock with the default buffer size of 4. Also, my test for one producer and two consumers showed a deadlock, as did my test for two producers and one consumer. One producer and one consumer worked fine. When I changed the notify() to notifyAll(), all the tests passed. -- WayneConrad