//---------------------------------------------------------------------- // Dining Philosphers © 1997 David Whitney // // Definitions of the Stick, StickSetting, DiningPhilosophers objects. // // The Dining Philosphers is a classic multiprocessing problem involving // five philospohers seated around a table with a single chopstick placed // between each philospher and a bowl of food in the middle. // The Philosophers sit and think, but sometimes they get hungry. In order // to eat they need to pick up the two sticks on either side of them. This // works fine as long as two neighboring philosphers don't eat at the same time. // This algorithm makes sure that there is no deadlock (all philosphers // with one stick in their hands waiting for the other stick which will never // be available) and that no philosopher starves be being unable to get both // sticks in a timely manner. // // The interesting bit of code is in StickSetting, where synchronized methods // assure no two philosphers can grab the same stick at the same time. There // is also a "magic" stick that moves around the table that, when picked up by // a philosopher, must be dropped immediately, thus ensuring no deadlock and no // starvation. // // Acknowledgement: // Graphics, audio, and inspiration taken from the book, Hooked On Java. // All code and object oriented design is original and © 1997 David Whitney. // // Permission granted to use all code herein, provided credit is given and // this copyright notice appears on all copies of the software. // // David Whitney dwhitney@cs.stanford.edu // August 9, 1997 //---------------------------------------------------------------------- // package EDU.Stanford.cs.dwhitney.diningPhilosophers; import Philosopher; import java.util.*; //---------------------------------------------------------------------- // Dining Philosphers // // This class creates five philospohers and starts them eating and thinking. // It also controls their threads via the thread group. //---------------------------------------------------------------------- class DiningPhilosophers { int _numPhilosophers; Philosopher _philosopher[]; Stick _stick[]; StickSetting _place[]; Thread _thread[]; ThreadGroup _philosopherGroup; //---------------------------------------------------------------------- // Constructor -- create the table and the philosophers. //---------------------------------------------------------------------- public DiningPhilosophers( int inPhilosopherCount ) { // initialize arrays _numPhilosophers = inPhilosopherCount; _philosopher = new Philosopher[ _numPhilosophers ]; _thread = new Thread[ _numPhilosophers ]; _stick = new Stick[ _numPhilosophers ]; _place = new StickSetting[ _numPhilosophers ]; // Set the table for (int i = 0; i < _numPhilosophers; i++) { _place[i] = new StickSetting(); // the place settings _place[i].placeStick( new Stick() ); // the utensils _place[0].getStick().setIsMagic( true ); // make one stick special } // Create the philosophers // _philosopherGroup = new ThreadGroup( temp, "philosophers"); _philosopherGroup = Thread.currentThread().getThreadGroup(); for ( int i = 0; i < _numPhilosophers; i++) { _philosopher[i] = new Philosopher( i, _place[i], _place[(i+1) % _numPhilosophers]); System.out.println( "A philosopher is born" ); _thread[i] = new Thread( _philosopherGroup, _philosopher[i] ); _thread[i].setPriority( Thread.MIN_PRIORITY ); } } //---------------------------------------------------------------------- // Accessors //---------------------------------------------------------------------- public int getPhilosopherCount() { return _numPhilosophers; } public Philosopher getPhilosopher(int i) { return _philosopher[i]; } public int getSpeed() { return _philosopher[0].getSpeed(); } public float getThinkChance() { return _philosopher[0].getThinkChance(); } public float getEatChance() { return _philosopher[0].getEatChance(); } public void setSpeed( int inSpeed ) { for (int i = 0; i < _numPhilosophers; i++ ) _philosopher[i].setSpeed( inSpeed ); } public void setThinkChance( float inChance ) { for (int i = 0; i < _numPhilosophers; i++ ) _philosopher[i].setThinkChance( inChance ); } public void setEatChance( float inChance ) { for (int i = 0; i < _numPhilosophers; i++ ) _philosopher[i].setEatChance( inChance ); } //---------------------------------------------------------------------- // addObserver -- let someone watch the philosophers. //---------------------------------------------------------------------- public void addObserver( Observer inObserver ) { for (int i = 0; i < _numPhilosophers; i++ ) _philosopher[i].addObserver( inObserver ); } //---------------------------------------------------------------------- // Thread group operations //---------------------------------------------------------------------- public void start() { System.out.println("Philosophers started."); for ( int i = 0; i < _numPhilosophers; i++) _thread[i].start(); } public void suspend() { System.out.println("Philosophers paused."); // _philosopherGroup.suspend(); // illegal in applet ?!? for (int i = 0; i < _numPhilosophers; i++) _thread[i].suspend(); } public void resume() { System.out.println("Philosophers resumed."); // _philosopherGroup.resume(); for (int i = 0; i < _numPhilosophers; i++) _thread[i].resume(); } public void stop() { System.out.println("Philosophers nuked."); for (int i = 0; i < _numPhilosophers; i++) _thread[i].stop(); _philosopherGroup.stop(); resume(); /* if suspended, so they can stop */ } } //---------------------------------------------------------------------- // StickSetting // // This is the shared resource that the philosophers are watching, // not so much the stick itself. //---------------------------------------------------------------------- class StickSetting { Stick _stick = null; public Stick getStick() { return _stick; } //---------------------------------------------------------------------- // pickUpStick -- wait for a stick to show up, grab it when it's there. //---------------------------------------------------------------------- public synchronized Stick pickUpStick() { while (_stick == null) { try { wait(); } catch (InterruptedException ex) {}; } Stick s = _stick; _stick = null; return s; } //---------------------------------------------------------------------- // placeStick -- drop a stick on the table, tell others it's there. //---------------------------------------------------------------------- public synchronized void placeStick( Stick inStick ) { if (_stick != null) System.err.println("ERROR: Two sticks in one place setting!"); _stick = inStick; notify(); } } //---------------------------------------------------------------------- // Stick //---------------------------------------------------------------------- class Stick { boolean _isMagic = false; public boolean isMagic() { return _isMagic; } public void setIsMagic( boolean inMagic ) { _isMagic = inMagic; } } // end of class Stick