import java.awt.Color; import java.util.Enumeration; public class DrunkPhilosopher extends RandomWalker { // OVERVIEW: A DrunkPhilosopher is a philosopher who walks around randomly until finding a // colleague (that is, a neighboring object that is also a DrunkPhilosopher). // When a philosopher finds a colleague, and the start philosophizing (and stop // wandering randomly). private boolean inTurn; // Currently in the middle of a turn (used for coloring) private DrunkPhilosopher colleague; private boolean isPhilosophizing; private boolean isArguing; private String quote; private String name; // We want our philosophers to have different names, so we use a class instance variable // to count the number of philosophers created. static private int counter = 0; static synchronized private String getNextName () { counter++; return "Philo" + counter; } public DrunkPhilosopher () { inTurn = false; colleague = null; isPhilosophizing = false; isArguing = false; quote = "I drink, therefore I am."; // All drunk philosophers philosophize the same way (but they still argue). name = getNextName (); } public Color getColor() { if (inTurn) { return Color.white; } else { if (isArguing) { return Color.red; } else if (isPhilosophizing) { return Color.green; } else { return Color.yellow; } } } //@nowarn NonNullResult // ESC/Java doesn't know Color constants are not null public synchronized void philosophize () { isPhilosophizing = true; isArguing = false; System.err.println (name + "[Thread " + Thread.currentThread().getName () + "] says " + quote); delay (1000); if (colleague != null) { // Need a colleague to start and argument. colleague.argue (); } } public synchronized void argue () { isPhilosophizing = false; isArguing = true; System.err.println (name + "[Thread " + Thread.currentThread().getName () + "] argues: No! " + quote); // delay (600); isArguing = false; } synchronized public void executeTurn () throws RuntimeException // Note: requires isInitialized is inherited from SimObject // EFFECTS: Picks a random direction and tries to move that way. // If the move is successful, return true. If the move fails // because the spot being attempted to move into is already // occupied then return false. { inTurn = true; if (colleague != null) { if (!isPhilosophizing && !isArguing) { philosophize (); // delay (600); } } else { synchronized (getGrid ()) { super.executeTurn (); // Continue walking around randomly Enumeration neighbors = getNeighbors (); while (neighbors.hasMoreElements ()) { SimObject neighbor = (SimObject) neighbors.nextElement (); if (neighbor instanceof DrunkPhilosopher) { // Found a colleague! DrunkPhilosopher philo = (DrunkPhilosopher) neighbor; System.err.println (name + "[Thread " + Thread.currentThread().getName () + "] found a colleague: " + philo.name); synchronized (philo) { // Make sure philo doesn't get a different colleague before setting. if (philo.colleague == null) { colleague = philo; philo.colleague = this; break; // out of the while loop, only need one colleague } } } } } } inTurn = false; } }