package net.catpad.infobus.test.dinner;
import java.util.ArrayList;
import java.util.List;
import net.catpad.infobus.ServiceId;
import net.catpad.infobus.ServiceLauncher;
import net.catpad.infobus.ServiceThreadAlreadyRunningException;
/**
* This is the implementation of the Dijkstra's Dining Philosophers problem.
* (see, for example, http://en.wikipedia.org/wiki/Dining_philosophers).
*
* This solutions prevents deadlock by requiring a philosopher to start eating
* only when he can take both forks from the table. If at least one of the forks
* is not available, the philosopher will not take another one as well.
*
* This solution also achieves some fairness by making each philosopher to notify
* his neighbours that he has finished his meal, i.e. that at least one of
* their forks is available.
*
* There is an arbitrary number of philosophers in this program and the same
* number of service threads: one thread serves one philosopher. In the beginning
* the main application wakes up all the philosophers by sending them
* WakeUpCommQueueItem communication queue item which encapsulates the logic of
* the philosopher's behaviour. The same item is used when the philosophers
* notify each other about their forks availability.
*
* At the end each philosopher reports about how many times he ate during the dinner.
* All tests has shown that a very good fairness is indeed achieved.
*
* @author Michael Gertelman
*
*/
public class InfoBusTestDinner {
// The table with 5 forks
public static final Table table = new Table();
// We have a very large number of philosophers
public static final int PHILOSOPHERS_NUMBER = 1000;
private final static ArrayList<Philosopher> philosophers =
new ArrayList<Philosopher>(PHILOSOPHERS_NUMBER);
private static List<ServiceId> idList;
public static void main(String[] args) {
ServiceLauncher launcher = new ServiceLauncher();
try {
// Start all service threads that will serve all our philosophers
idList = launcher.startServices(0, PHILOSOPHERS_NUMBER-1, "Service for Philosopher ");
} catch (ServiceThreadAlreadyRunningException e) {
System.err.println(e.getMessage());
}
int counter = 0;
for (ServiceId id : idList) {
// Create a new philosopher which will be served by the current service thread
Philosopher philosopher = new Philosopher(counter,id);
philosophers.add(counter, philosopher);
// Wake up the philosopher's service thread and let it compete for the forks
launcher.getInfoBus().postItem(id, new WakeUpCommQueueItem(launcher, philosopher));
counter++;
}
// The dinner is going to be 1 minute long
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Enough thinking and eating!
launcher.shutdownGracefully();
// Wait until all service threads finish their tasks
try {
launcher.join();
} catch (InterruptedException e) {
System.err.println("Join interrupted!");
}
System.out.println("The dinner is over");
// Let's see how fair it was...
for (Philosopher philosopher : philosophers) {
philosopher.printStatistics();
}
}
public static Philosopher getPhilosopher(int number) {
return philosophers.get(number);
}
}
|