/* file PhilosopherArea.java */ import java.awt.*; public class PhilosopherArea extends Canvas { PhilAnimator controller; Image[] imgs = new Image[3]; Chopstick[] chopsticks = new Chopstick[NUMPHILS]; String[] names = { "Arisduktle" , "Dukrates", "Pythagorduke", "Duko", "Dukimedes" }; static final int NUMPHILS = 5; private static final double MARGIN = 10.0f; private double spacing; private Philosopher[] philosophers = new Philosopher[NUMPHILS]; private boolean[] redraw = new boolean[NUMPHILS]; private boolean running = false; public PhilosopherArea(PhilAnimator controller) { super(); this.controller = controller; MediaTracker mt; mt = new MediaTracker(this); imgs[0] = controller.getImage(controller.getCodeBase(), "hungryduke.gif"); mt.addImage(imgs[0], 0); imgs[1] = controller.getImage(controller.getCodeBase(), "rightspoonduke.gif"); mt.addImage(imgs[1], 1); imgs[2] = controller.getImage(controller.getCodeBase(), "bothspoonsduke.gif"); mt.addImage(imgs[2], 2); try { mt.waitForID(0); mt.waitForID(1); mt.waitForID(2); } catch (java.lang.InterruptedException e) { System.out.println("Couldn't load one of the images"); } spacing = imgs[0].getWidth(this) + MARGIN; createPhilosophersAndChopsticks(); } public void paint(Graphics g) { g.setColor(Color.lightGray); g.fillRect(0, 0, size().width, size().height); for (int i = 0; i < NUMPHILS; i++) { redraw[i] = true; } update(g); } public void update(Graphics g) { for (int i = 0; i < NUMPHILS; i++) { if (redraw[i]) { philosophers[i].paint(g); redraw[i] = false; } } } public boolean mouseDown(java.awt.Event evt, int x, int y) { if (running) { for (int i = 0; i < NUMPHILS; i++) philosophers[i].suspend(); } else { for (int i = 0; i < NUMPHILS; i++) philosophers[i].resume(); } running = !running; return true; } public synchronized void repaintPhil(int id) { redraw[id] = true; repaint(); } public void startPhilosophers() { for (int i = 0; i < NUMPHILS; i++) philosophers[i].start(); running = true; } public void stopPhilosophers() { for (int i = 0; i < NUMPHILS; i++) philosophers[i].stopRequested(); } public void createPhilosophersAndChopsticks() { double x, y; double radius = 80.0; double centerAdj = 85.0; double radians; /* for a straight line y = MARGIN; */ for (int i = 0; i < NUMPHILS; i++) chopsticks[i] = new Chopstick(); for (int i = 0; i < NUMPHILS; i++) { /* for a straight line x = i * spacing; */ radians = i*(2.0 * Math.PI /(double)NUMPHILS); x = Math.sin(radians) * radius + centerAdj; y = Math.cos(radians) * radius + centerAdj; philosophers[i] = new Philosopher(this, x, y, i); repaintPhil(i); } } } _________________________________________________________________ /* file PhilAnimator.java */ import java.awt.*; public class PhilAnimator extends java.applet.Applet { private Button stopStartButton = new Button("start"); // delays can go from 500 to 10,000 // (they get multiplied by 100 in Philosopher Scrollbar grabDelaySlider = new Scrollbar(Scrollbar.HORIZONTAL, 5, 100, 0, 100); private Label label = new Label(" 500 milliseconds"); private FramedArea framedArea; public void init() { GridBagLayout gridBag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridBag); framedArea = new FramedArea(this); c.fill = GridBagConstraints.BOTH; c.weighty = 1.0; c.gridwidth = GridBagConstraints.REMAINDER; //end row gridBag.setConstraints(framedArea, c); add(framedArea); c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1.0; c.weighty = 0.0; gridBag.setConstraints(stopStartButton, c); add(stopStartButton); c.gridwidth = GridBagConstraints.RELATIVE; //don't end row c.weightx = 1.0; c.weighty = 0.0; gridBag.setConstraints(grabDelaySlider, c); add(grabDelaySlider); c.weightx = 0.0; c.gridwidth = GridBagConstraints.REMAINDER; //end row gridBag.setConstraints(label, c); add(label); validate(); } public boolean handleEvent(Event e) { if (e.target == stopStartButton) { if (stopStartButton.getLabel().equals("stop/reset")) { framedArea.stopButton(); stopStartButton.setLabel("start"); } else if (stopStartButton.getLabel().equals("start")) { framedArea.startButton(); stopStartButton.setLabel("stop/reset"); } } else if (e.target == grabDelaySlider) { label.setText(String.valueOf(100*grabDelaySlider.getValue()) + " milliseconds"); } return false; } } _________________________________________________________________ /* file Philosopher.java */ import java.awt.*; public class Philosopher extends Thread { private Chopstick leftStick, rightStick; private double x, y; private boolean sated; private PhilosopherArea parent; private int position; private boolean stopRequested = false; public Philosopher(PhilosopherArea parent, double x, double y, int position) { super(parent.names[position]); this.parent = parent; this.position = position; this.x = x; this.y = y; // identify the chopsticks to my right and left this.rightStick = this.parent.chopsticks[position]; if (position == 0) { this.leftStick = this.parent.chopsticks[this.parent.NUMPHILS-1]; } else { this.leftStick = this.parent.chopsticks[position-1]; } // I'm hungry this.sated = false; } public void run() { int grabDelay; while (stopRequested == false) { try { grabDelay = parent.controller.grabDelaySlider.getValue() * 100; sleep((int)(Math.random() * grabDelay)); rightStick.grab(this); parent.repaintPhil(position); grabDelay = parent.controller.grabDelaySlider.getValue() * 100; sleep((int)(Math.random() * grabDelay)); leftStick.grab(this); parent.repaintPhil(position); grabDelay = parent.controller.grabDelaySlider.getValue() * 100; sleep((int)(Math.random() * grabDelay)); eat(); grabDelay = parent.controller.grabDelaySlider.getValue() * 100; sleep((int)(Math.random() * grabDelay * 4)); sated = false; parent.repaintPhil(position); } catch (java.lang.InterruptedException e) { } } } public void eat() { rightStick.release(this); leftStick.release(this); sated = true; parent.repaintPhil(position); } public void paint(Graphics g) { g.setColor(Color.lightGray); g.fillRect((int)x, (int)y, parent.imgs[0].getWidth(parent), parent.imgs[0].getHeight(parent)+25); if (sated == false) { if (rightStick.owner == this && leftStick.owner != this) { // got left only g.drawImage(parent.imgs[1], (int)x, (int)y, parent); } else if (rightStick.owner == this && leftStick.owner == this) { // got both g.drawImage(parent.imgs[2], (int)x, (int)y, parent); } else { // got nothing g.drawImage(parent.imgs[0], (int)x, (int)y, parent); } } else { g.drawImage(parent.imgs[0], (int)x, (int)y, parent); g.setColor(Color.black); g.drawString("Mmm!", ((int)(x)+8), ((int)(y)+parent.imgs[0].getHeight(parent)+13)); } } public void stopRequested() { stopRequested = true; } }