/** * This class hands control alternately to two threads. The threads * track whose turn it is by alternately setting the 'whoseTurn' * string to be that of their opponent. */ public class PingPong { // state variable identifying whose turn it is. String whoseTurn = null; /** * This method is where the threads synchronize. * When the player thread enters hit it acquires the * monitor for this object. If it is not this threads * turn, the thread goes into a wait. If it is this * thread's turn, it sets the state variable to its * opponent, notifies all threads that are waiting on * this monitor and then returns. */ public synchronized boolean hit(String opponent) { String x = Thread.currentThread().getName(); /* Take care of startup condition */ if (whoseTurn == null) { whoseTurn = x; return true; } /* Take care of end condition */ if (whoseTurn.compareTo("DONE") == 0) return false; if (opponent.compareTo("DONE") == 0) { whoseTurn = opponent; notifyAll(); return false; } if (x.compareTo(whoseTurn) == 0) { System.out.println("PING! ("+x+")"); whoseTurn = opponent; notifyAll(); } else { try { /* * I've used a hack here to see if I come out of * the wait because I've been notified or because * I've timed out (which would be an indication of * deadlock.) */ long t1 = System.currentTimeMillis(); wait(2500); if ((System.currentTimeMillis() - t1) > 2000) { System.out.println("****** TIMEOUT! "+x+ " is waiting for "+whoseTurn+" to play."); } } catch (InterruptedException e) { } } return true; // keep playing. } }