Created
December 9, 2016 15:39
-
-
Save antgustech/c34b8931e5675c1fc3d7e6f7be6f84b0 to your computer and use it in GitHub Desktop.
Eating philosofer example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main; | |
import java.util.concurrent.Semaphore; | |
/** | |
* Thread representing a philosofer. | |
* | |
* @author Anton Gustafsson | |
* | |
*/ | |
public class Philosofer implements Runnable { | |
private byte i; | |
private Semaphore mutex; | |
private Semaphore forks; | |
private final short THINKING = 0; | |
private final short HUNGRY = 1; | |
private final short EATING = 2; | |
private final byte[] states; | |
/** | |
* Initializes variables. | |
* | |
* @param states - byte array determing which state this philosofer is in. | |
* @param i - the name of this philosofer. | |
* @param mutex - a binary semaphore acting mutex.. | |
* @param forks - a semaphore lock which has 4 forks. | |
*/ | |
public Philosofer(byte[] states, byte i, Semaphore mutex, Semaphore forks) { | |
this.states = states; | |
this.i = i; | |
this.mutex = mutex; | |
this.forks = forks; | |
states[i] = THINKING; | |
} | |
/** | |
* Lifecycle of the philosofer. | |
*/ | |
@Override | |
public void run() { | |
while (true) { | |
prt(); | |
think(); | |
prt(); | |
takeForks(); | |
prt(); | |
eat(); | |
prt(); | |
putForks(); | |
prt(); | |
} | |
} | |
/** | |
* Philosofer is thinking for a random amount of time. | |
*/ | |
private void think() { | |
try { | |
Thread.sleep((int) (Math.random() * 1000)); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
} | |
/** | |
* Philosofer is eating for random amount of time. | |
* Just calls think as they essential do the same thing. | |
*/ | |
private void eat() { | |
think(); | |
} | |
/** | |
* Method that takes the forks from the table. First it locks | |
* with a mutex then it changes state to hungry and check if it's | |
* neighbors are already eating. | |
*/ | |
private void takeForks() { | |
try { | |
System.out.println("MUTEX LOCK"); | |
mutex.acquire(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
states[i] = HUNGRY; | |
prt(); | |
checkNeighbors(i); | |
mutex.release(); | |
System.out.println("MUTEX UNLOCK"); | |
} | |
/** | |
* Method that put down 2 forks to the table. Then it locks the mutex, changes it | |
* state to thinking and then checks if it's neignoring philosofers | |
* want to eat. | |
* | |
*/ | |
private void putForks() { | |
forks.release(2); | |
try { | |
mutex.acquire(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
states[i] = THINKING; | |
checkNeighbors(left(i)); | |
checkNeighbors(right(i)); | |
mutex.release(); | |
} | |
/** | |
* Checks if any of the neighbors are eating. | |
* | |
* @param i | |
*/ | |
private void checkNeighbors(short i) { | |
if (states[i] == HUNGRY && left(i) != EATING && right(i) != EATING) { | |
states[i] = EATING; | |
try { | |
forks.acquire(2); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
/** | |
* Checks if we are out of bounds to the left. if so, return the last index. | |
* | |
* @param i | |
* @return | |
*/ | |
private short left(short i) { | |
if (i - 1 < 0) { | |
return states[4]; | |
} | |
return states[i - 1]; | |
} | |
/** | |
* Checks out of bounds to the right. If so, return the first element. | |
* | |
* @param i | |
* @return | |
*/ | |
private short right(short i) { | |
if (i + 1 > 4) { | |
return states[0]; | |
} | |
return states[i + 1]; | |
} | |
private void prt() { | |
short s = states[i]; | |
if (s == HUNGRY) { | |
System.out.println("Philosofer " + i + " Is " + " (HUNGRY)"); | |
} else if (s == THINKING) { | |
System.out.println("Philosofer " + i + " Is " + " (THINKING)"); | |
} else if (s == EATING) { | |
System.out.println("Philosofer " + i + " Is " + " (EATING)"); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main; | |
import java.util.concurrent.Semaphore; | |
/** | |
* This class starts the program, creates threads and call their start method. | |
* @author Anton Gustafsson | |
* | |
*/ | |
public class Start { | |
/** | |
* Creates and starts new threads. One for each Philosofer. | |
* The state is used to keep track of what each philosofer is doing | |
* and the semaphores are of course there to represent forks and mutex. | |
*/ | |
public static void main(String[] args) { | |
byte[] states = new byte[5]; | |
Semaphore mutex = new Semaphore(1); | |
Semaphore forks = new Semaphore(4); | |
Thread p0 = new Thread(new Philosofer(states,(byte) 0, mutex, forks )); | |
Thread p1 = new Thread(new Philosofer(states,(byte) 1, mutex, forks )); | |
Thread p2 = new Thread(new Philosofer(states,(byte) 2, mutex, forks )); | |
Thread p3 = new Thread(new Philosofer(states,(byte) 3, mutex, forks )); | |
Thread p4 = new Thread(new Philosofer(states,(byte) 4, mutex, forks )); | |
p0.start(); | |
p1.start(); | |
p2.start(); | |
p3.start(); | |
p4.start(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment