Concurrent Programming with Java
Lab Manual, Version 1.0, F. Astha Ekadiyanto,
2002.
The Philosopher Class is the Thread that are repetitively trying to acquire ownership of the forks. Each philosopher will have 5 consecutive states as shown in the figure below and implemented in the run() method.
The Thinking Process is represented by a random sleeping time in the thread. The Hungry Process consists of two steps namely taking the first fork and the second fork. In the current definition all philosophers will take first the fork on the right then after that the left one. The Eating Process is also represented by a random sleeping time in the thread. The Put down Forks Process is simply putting all the forks in hand. The Class also defines some constants to represent the philosopher's states. The Class Constructor is simply defining the Philosopher ID as well as the left and right Forks relatively. Observe that we also define a static variable called speed that can be used to control the range of sleeping time when the philosopher is in either Thinking Process or Eating Process. This speed variable is a public variable that allow other objects (in this case the Applet) to modify it. The Philosopher Class together with the Fork
Class exhibit the other deadlock symptoms which are Incremental
acquisition, and No pre-emption. |
The implementation of Philosopher Class is also very straight forward as the followings:
Class name: Philosopher
public class Philosopher extends Thread /** * The class Philosopher implements Philosopher (the accessing process). * Modified from Stephan Fischli's Phillosophers Code */ { /** * The state of the philosopher. */ private int state; public static final int THINKING = 0; public static final int TAKING_FIRST_FORK_LEFT = 1; public static final int TAKING_FIRST_FORK_RIGHT = 2; public static final int TAKING_SECOND_FORK_RIGHT = 3; public static final int TAKING_SECOND_FORK_LEFT = 4; public static final int EATING = 5; public static int speed = 5000; /** * The number of the philosopher. */ private int number; /** * The fork on the left. */ private Fork leftFork; /** * The fork on the right. */ private Fork rightFork; /** * Constructs a Philosopher object. * @param number the number of the philosopher * @param leftFork the fork on the left * @param rightFork the fork on the right */ public Philosopher( int number, Fork leftFork, Fork rightFork ) { this.number = number; this.leftFork = leftFork; this.rightFork = rightFork; state = THINKING; } /** * Returns the number of the philosopher. */ public int number() { return number; } /** * Returns the state of the philosopher. */ public int state() { return state; } /** * Starts the philosopher. */ public void run() { while ( true ) { think(); takeFirstFork(); //Must always be the first! takeSecondFork();//Must always come after the first fork! eat(); putDownForks(); } } /** * Lets the philosopher think. */ public void think() { state = THINKING; int time = (int)(speed*(Math.random())); try { sleep( time ); } catch ( InterruptedException e ) {} } /** * Lets the philosopher take the first fork. * In this case it is the right fork first */ public void takeFirstFork() { state = TAKING_FIRST_FORK_RIGHT; try { sleep( 100 ); } //Process of taking fork may take a little time catch ( InterruptedException e ) {} rightFork.get(); } /** * Lets the philosopher take the second fork. * In this case it is the left fork second. */ public void takeSecondFork() { state = TAKING_SECOND_FORK_LEFT; try { sleep( 100 ); } //Process of taking fork may take a little time catch ( InterruptedException e ) {} leftFork.get(); } /** * Lets the philosopher eat. */ public void eat() { state = EATING; int time = (int)(speed*(Math.random())); try { sleep( time ); } catch ( InterruptedException e ) {} } /** * Lets the philosopher put down the forks. */ public void putDownForks() { leftFork.put(); rightFork.put(); } } |