Dining Philosopher's Problem (Java Implementation Using Reentrant Lock)

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