Hi Guys,
Firstly, i'd like to state that this is a homework question which means i'm not looking for a direct solution to my problem. Just subtle hints on how to improve etc. I'm posting this here as I want to try and get a better understanding of Java's wait() and Notify(). Thanks.
I'm happy that this works and i'd be willing to submit it as is but my reason for posting is I want to find any bugs in it and more importantly the best way of doing things.
Any ideas on this are greatly appreciated, Thanks :)
So, here is the problem that I have been presented with. My "working" solution will follow.
Problem:
Three smokers are sitting around a table. Only one person can smoke at a time. To smoke a smoker need three ingredients: tobacco, paper and a match. Each smoker has an infinite supply of all three ingredients. The agent places two ingredients on the table and waits for a smoker to make a cigarette and smoke it. When the smoker is finished smoking it notifies the agent that another round of ingredients should be places on the table to allow smoking to continue. In this way smokers can continue smoking in some order forever!
Your task is to write a program that simulates behaviour of the smokers and the smokers agent.
HINT: Think of the smokers and agent as threads the share a table.
Here is my solution:
public class Question_5 {
public static void main(String args[]) {
/* Rules:
* Smokers have unlimited matches.
* They need tobacco and paper to be placed on the
* table to make and smoke a cigarette.
*/
Table table = new Table();
Agent agent = new Agent(table);
Smoker s1 = new Smoker(table, agent, 1);
Smoker s2 = new Smoker(table, agent, 2);
Smoker s3 = new Smoker(table, agent, 3);
agent.start();
s1.start();
s2.start();
s3.start();
}
}
class Table {
boolean tobacco; // Is tobacco on the table.
boolean paper; // Is paper on the table.
boolean notify; // Used for the agent, should it be notifed.
public Table() {
// Initial setup says nothing on the table and notify the agent
// to populate the table with ingredients.
this.tobacco = false;
this.paper = false;
this.notify = true;
}
}
class Agent extends Thread {
Table table;
public Agent(Table table) {
this.table = table;
}
public void alert() {
synchronized(table) {
System.out.println("Agent alerted..");
table.notify = true;
table.notifyAll();
}
}
public void run() {
try {
synchronized (table) {
while(true) {
while(!table.notify) {
System.out.println("Agent is observing..!");
table.wait();
}
System.out.println("Agent populates table with tobacco and paper");
table.tobacco = true;
table.paper = true;
table.notify = false;
table.notifyAll();
}
}
}
catch (InterruptedException e) {}
}
}
class Smoker extends Thread {
String smStages[] = {"Rolling", "Lighting", "Smoking", "Putting out"};
Table table;
Agent agent;
int id;
public Smoker(Table table, Agent agent, int id) {
this.table = table;
this.agent = agent;
this.id = id;
}
public void run() {
try {
synchronized (table) {
while(true)
{
while(!(table.tobacco && table.paper)) {
System.out.println("Smoker #"+id+" waiting!");
table.wait();
}
if(table.tobacco && table.paper) {
table.paper = false;
table.tobacco = false;
System.out.print("Smoker #"+id+" is :");
for(int i = 0; i < 4; i++) {
// It takes 10 seconds for a smoker to roll, light, smoke and put out a cigarette.
System.out.print(smStages[i]+" ");
Thread.sleep(250);
}
System.out.println();
agent.alert(); // Alert the agent that current smoker is finished.
}
}
}
}
catch (InterruptedException e) {}
}
}