This is a sample code for the famous dining philosophers problem that I implemented using java locks provided.
To implement the action of taking a stick waiting a random amount of time for the other stick to be available and then keeping the stick back on the table, I have used the java Reentrant lock class which is a sub class of Lock class.
Here is the code. I have used System.out.println(); only for the purpose of demonstrating the actions. Otherwise try to avoid that in multi-threaded environments as printing something is kind of accessing an output device. Since accessing an I/O device is a synchronized process, it would significantly degrade the performance of the overall execution.
import java.util.Random;
public class Philosopher implements Runnable {
private final int id;// id of the philosopher,the left stick has the same id
// and the right stick has id+1
private Table table;
private static Object lock = new Object();// this is the lock used to create
// the waiting pool of
// philosophers
/**
* @param- id
* @param-tb Takes the id of the philosopher and the object of the table
* */
public Philosopher(int id, Table tb) {
this.id = id;
this.table = tb;
}
public int getId() {
return id;
}
/**
* first all threads are called wait() to stay in 'lock' objects waiting
* pool when the notifyAll() is called from another thread, all philosopher
* threads start action takes right stick if successful takes left stick and
* then attempts to eat some noodles after eating thinks for a random amount
* of time then keeps the sticks back first the left and then the right if
* unable to take the left stick, then right stick is kept back
* */
@Override
public void run() {
synchronized (lock) {
try {
System.out.println("philosopher " + id + " is getting ready");
lock.wait();
} catch (InterruptedException e) {
}
}
boolean isNoodlesRemaining = true;
while (isNoodlesRemaining) {
if (this.table.getRightStick(id)) {
if (this.table.getLeftStick(id)) {
isNoodlesRemaining = this.aquireBowlAndEat();//false if bowl is empty
this.think();
this.table.unlockLeftStick(id);
//if the bowl is empty this loop will exit
}
this.table.unlockRightStick(id);
}
}
System.out.println("philosopher " + id + " is stopping");
System.out.println("Current noodles= "
+ table.getBowl().getCurrentNoodels());
}
public void think() {
System.out.println("philosopher " + id + " is thinking");
try {
Thread.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
}
}
public boolean aquireBowlAndEat() {
Bowl bowl = table.getBowl();
synchronized (bowl) {
if (bowl.isEmplty()) {
return false;
}
bowl.eatFromBowl(id);
return true;
}
}
/**
* Every philosopher thread is started and sent to waiting state it waits on
* 'lock' object's waiting pool untill main thread invokes lock.notifyAll()
* */
public static void main(String[] args) {
Table table = new Table(10);
Philosopher[] pQueue = new Philosopher[10];
for (int id = 0; id < 10; id++) {
Philosopher p = new Philosopher(id, table);
pQueue[id] = p;
Thread t = new Thread(p);
t.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
synchronized (lock) {
lock.notifyAll();
}
}
}
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Table {
private final int NUM_OF_PEOPLE;
private static Bowl bowl = new Bowl();// bowl is a static shared object
// among philosopher threads
private Stick[] sticks;
Table(int numOfPeople) {
NUM_OF_PEOPLE = numOfPeople;
this.sticks = new Stick[NUM_OF_PEOPLE];
for (int i = 0; i < NUM_OF_PEOPLE; i++) {
sticks[i] = new Stick(new ReentrantLock());
// uses reentrant lock in order to provide
// lock mechanism that returns after a certain amount of
// time if the lock is not acquired or any interrupt did not occur
}
}
public boolean getRightStick(final int id) {
if (id == NUM_OF_PEOPLE - 1 && sticks[0] != null) {
System.out.println("Right stick taken by philosopher " + id);
return sticks[0].getStick();
} else {
if (sticks[id + 1] != null) {
System.out.println("Right stick taken by philosopher " + id);
return sticks[id + 1].getStick();
}
try {
throw new SticksNotInitializedException();
} catch (SticksNotInitializedException e) {
return false;
}
}
}
public boolean getLeftStick(final int id) {
if (sticks[id] != null) {
System.out.println("Left stick taken by philosopher " + id);
return sticks[id].getStick();
} else {
try {
throw new SticksNotInitializedException();
} catch (SticksNotInitializedException e) {
return false;
}
}
}
public void unlockLeftStick(int id) {
System.out.println("philosopher " + id + " is keeping the left stick");
sticks[id].unlockStick();
}
public void unlockRightStick(int id) {
System.out.println("philosopher " + id + " is keeping the right stick");
if (id == NUM_OF_PEOPLE - 1) {
sticks[0].unlockStick();
return;
}
sticks[id + 1].unlockStick();
}
public Bowl getBowl() {
return bowl;
}
}
import java.util.Random;
public class Bowl {
private static final int MAX_NOODLES = 100;
private int currentNoodles = MAX_NOODLES;
public void eatFromBowl(int id) {
this.currentNoodles -= 1;
try {
System.out.println("philosopher "+id+" is eating from the bowl");
Thread.sleep(new Random().nextInt(500));
} catch (InterruptedException e) {
}
}
public boolean isEmplty() {
if (currentNoodles == 0) {
return true;
} else
return false;
}
public int getCurrentNoodels(){
return currentNoodles;
}
}
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
public class Stick {
private Lock lock;
Stick(Lock lock) {
this.lock = lock;
}
public boolean getStick() {
boolean isTaken = false;
try {
isTaken = this.lock.tryLock(100, TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) {
}
return isTaken;
}
public void unlockStick(){
this.lock.unlock();
}
}
Comments
Post a Comment