//---------------------------------------------------------------------- // class Philosopher © 1997 David Whitney // // A philosopher has two hands, eats, thinks and waits for sticks. // We subscribe to the Model-View pattern and let others know what we're doing // using the Observer interface. Any Observer that observes us will get // notification whenever our state changes or every "speed" milliseconds // that our state remains the same. // // David Whitney dwhitney@cs.stanford.edu // September 2, 1997 //---------------------------------------------------------------------- // package edu.stanford.cs.dwhitney.diningPhilosophers; import java.util.*; class Philosopher extends Observable implements Runnable { Hand _leftHand, _rightHand; // our hands that pick up sticks int _state; // what we're doig now. float _eatChance = 0.75f; // we'll keep eating 75% of the time float _thinkChance = 0.90f; // we'll keep thinking 90% of the time int _speed = 80; // milliseconds to wait after each action int _id; // which Philosopher we are. // States static final int Hungry_Waiting_Left = 1; static final int Hungry_Waiting_Right = 2; static final int Eating = 3; static final int Thinking = 4; //---------------------------------------------------------------------- // construct a philosopher and say where he should look for chopsticks //---------------------------------------------------------------------- public Philosopher( int inID, StickSetting inRightSetting, StickSetting inLeftSetting ) { _rightHand = new Hand( Hand.RIGHT, inRightSetting, this ); _leftHand = new Hand( Hand.LEFT, inLeftSetting, this ); setID( inID ); _state = Thinking; } //---------------------------------------------------------------------- // Accessors //---------------------------------------------------------------------- public int getID() { return _id; } public void setID( int inID ) { _id = inID; } public void setSpeed( int inSpeed ) { _speed = inSpeed; } public void setThinkChance( float inChance) { _thinkChance = inChance; } public void setEatChance( float inChance ) { _eatChance = inChance; } public float getThinkChance( ) { return _thinkChance; } public float getEatChance( ) { return _eatChance; } public int getSpeed() { return _speed; } public int getState() { return _state; } public Stick getLeftStick() { return _leftHand.getStick(); } public Stick getRightStick() { return _rightHand.getStick(); } //---------------------------------------------------------------------- // set our state, inform the world of the change, and wait a bit to keep // things slow. //---------------------------------------------------------------------- public void setState( int inState ) { _state = inState; setChanged(); notifyObservers(); // System.out.println( this ); try { Thread.sleep( _speed ); } catch (InterruptedException e) {}; } public void keep( int inState ) { setState( inState ); } //---------------------------------------------------------------------- // print philospher //---------------------------------------------------------------------- public String toString() { String str = new String(); str = "Philosopher #" + new Integer(getID()+1) + " is "; switch (_state) { case Eating: str += "eating."; break; case Thinking: str += "thinking."; break; case Hungry_Waiting_Right: str += "hungry, waiting for right stick."; break; case Hungry_Waiting_Left: str += "hungry, waiting for left stick."; break; } str += "(" + _eatChance + " " + _thinkChance + " " + _speed + ")"; return str; } //---------------------------------------------------------------------- // run thread - be a philospher //---------------------------------------------------------------------- public void run() { System.out.println( this ); for(;;) { think(); pickUpSticks(); eat(); dropSticks(); } } //---------------------------------------------------------------------- // think - spend some random time thinking, and state that we're thinking. //---------------------------------------------------------------------- void think() { setState( Thinking ); while (Math.random() < _thinkChance) keep( Thinking ); } //--------------------------------------------------------------- // eat - eat for some random amount of time, and state that we're eating //--------------------------------------------------------------- void eat() { setState( Eating ); while (Math.random() < _eatChance) keep( Eating ); } //---------------------------------------------------------------------- // pickUpSticks - a philosopher must have both sticks before it can eat. // If the magic stick is picked up first, put it back. //---------------------------------------------------------------------- void pickUpSticks() { Hand firstHand, secondHand; // randomly pick a hand to pick up stick with. Is this really necessary? // if ( 0.5f > Math.random()) { // firstHand = _leftHand; // secondHand = _rightHand; // } else { firstHand = _rightHand; secondHand = _leftHand; // } firstHand.pickupStick(); if (firstHand.getStick().isMagic()) { firstHand.dropStick(); secondHand.pickupStick(); firstHand.pickupStick(); } else { secondHand.pickupStick(); } } //---------------------------------------------------------------------- // dropSticks - swap sticks and place them back on the table. //---------------------------------------------------------------------- void dropSticks() { // swap sticks Stick leftstick = _leftHand.getStick(); _leftHand.setStick( _rightHand.getStick() ); _rightHand.setStick( leftstick ); _leftHand.dropStick(); _rightHand.dropStick(); } } //---------------------------------------------------------------------- // Hand // // A Philosopher's hand -- it knows where from and how to pickup sticks. //---------------------------------------------------------------------- class Hand { final static int LEFT = 1; final static int RIGHT = 2; StickSetting _stickSetting; // where is the stick we should pick up? int _side; // which hand are we? Stick _stick; // what's in our hand Philosopher _philosopher; // who we're attached to //---------------------------------------------------------------------- // constructor -- tell this hand who it's attached to and where to pick // up sticks. //---------------------------------------------------------------------- Hand( int inSide, StickSetting inStickSetting, Philosopher inPhilosopher ) { _side = inSide; _stickSetting = inStickSetting; _philosopher = inPhilosopher; setStick( null ); } //---------------------------------------------------------------------- // Accessors. //---------------------------------------------------------------------- Stick getStick() { return _stick; } void setStick(Stick inStick) { _stick = inStick; } //---------------------------------------------------------------------- // pickupStick -- tell philospher what its hand is doing and get the nearest stick //---------------------------------------------------------------------- void pickupStick() { if (_side == LEFT) _philosopher.setState( Philosopher.Hungry_Waiting_Left ); else _philosopher.setState( Philosopher.Hungry_Waiting_Right ); setStick( _stickSetting.pickUpStick() ); } //---------------------------------------------------------------------- // dropStick -- put stick back //---------------------------------------------------------------------- void dropStick() { _stickSetting.placeStick( _stick ); setStick( null ); } }