package diningphilosophers; import java.util.ArrayList; import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; enum PhilosopherState { Get, Eat, Pon } class Fork { public static final int ON_TABLE = -1; static int instances = 0; public int id; public AtomicInteger holder = new AtomicInteger(ON_TABLE); Fork() { id = instances++; } } class Philosopher implements Runnable { static final int maxWaitMs = 100; // must be > 0 static AtomicInteger token = new AtomicInteger(0); static int instances = 0; static Random rand = new Random(); AtomicBoolean end = new AtomicBoolean(false); int id; PhilosopherState state = PhilosopherState.Get; Fork left; Fork right; int timesEaten = 0; Philosopher() { id = instances++; left = Main.forks.get(id); right = Main.forks.get((id+1)%Main.philosopherCount); } void sleep() { try { Thread.sleep(rand.nextInt(maxWaitMs)); } catch (InterruptedException ex) {} } void waitForFork(Fork fork) { do { if (fork.holder.get() == Fork.ON_TABLE) { fork.holder.set(id); // my id shows I hold it return; } else { // someone still holds it sleep(); // check again later } } while (true); } public void run() { do { if (state == PhilosopherState.Pon) { // all that pondering state = PhilosopherState.Get; // made me hungry } else { // ==PhilosopherState.Get if (token.get() == id) { // my turn now waitForFork(left); waitForFork(right); // Ah needs me some foahks! token.set((id+2)% Main.philosopherCount); state = PhilosopherState.Eat; timesEaten++; sleep(); // eat for a while left.holder.set(Fork.ON_TABLE); right.holder.set(Fork.ON_TABLE); state = PhilosopherState.Pon; // ponder for a while sleep(); } else { // token.get() != id, so not my turn sleep(); } } } while (!end.get()); } } public class Main { static final int philosopherCount = 5; // token +2 behavior good for odd #s static final int runSeconds = 15; static ArrayList forks = new ArrayList(); static ArrayList philosophers = new ArrayList(); public static void main(String[] args) { for (int i = 0 ; i < philosopherCount ; i++) forks.add(new Fork()); for (int i = 0 ; i < philosopherCount ; i++) philosophers.add(new Philosopher()); for (Philosopher p : philosophers) new Thread(p).start(); long endTime = System.currentTimeMillis() + (runSeconds * 1000); do { // print status StringBuilder sb = new StringBuilder("|"); for (Philosopher p : philosophers) { sb.append(p.state.toString()); sb.append("|"); // This is a snapshot at a particular } // instant. Plenty happens between. sb.append(" |"); for (Fork f : forks) { int holder = f.holder.get(); sb.append(holder==-1?" ":String.format("P%02d",holder)); sb.append("|"); } System.out.println(sb.toString()); try {Thread.sleep(1000);} catch (Exception ex) {} } while (System.currentTimeMillis() < endTime); for (Philosopher p : philosophers) p.end.set(true); for (Philosopher p : philosophers) System.out.printf("P%02d: ate %,d times, %,d/sec\n", p.id, p.timesEaten, p.timesEaten/runSeconds); } }