Hi,
This is completely off topic but I figured I'd chance it in the hope someone here can help me. I'm having a problem with Java. It's a multi-threaded program where one "Agent" thread makes resources available to 3 other threads (Smokers). The smokers then use the resources, and notify the agent when they are finished so the agent can put another round on the table. The actual question is below.
I need to have this thing ready for tonight and I've tried everything I can think of. It just seems to hang every time. I think it's either not notifying properly or it's getting deadlock, but I can't see where as I have guards in place to prevent deadlock. What I'm saying pretty much is that if anyone can help, even to just point me in the right direction, or ballpark area, I would really appreciate it.
Here's the question:
Three smokers around a table. Only one can smoke at a time. To smoke a smoker needs 3 ingredients: tobacco, paper, and a match. Each smoker has an infinite supply of just one of these ingredients and must wait for the other two to be made available by a smokers agent. The smokers agent 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 notifys the agent that another round of ingredients should be places on the table to allow smoking to continue. In the way smokers can continue smoking in some order forever!
The code's below, I've put in comments where appropriate (I hope it makes sense):
________________________________________________________
class Main {
public static void main(String args[]) {
Resources resources = new Resources();
Agent agent = new Agent(resources);
Smoker smoker1 = new Smoker(0,resources);
Smoker smoker2 = new Smoker(1,resources);
Smoker smoker3 = new Smoker(2,resources);
agent.start();
smoker1.start();
smoker2.start();
smoker3.start();
// wait on threads to finish
try {
agent.join();
smoker1.join();
smoker2.join();
smoker3.join();
} catch(InterruptedException e){}
}
// end of Main class
}
// Resources class
class Resources {
volatile boolean tobacco;
volatile boolean paper;
volatile boolean match;
// default constructor
public Resources() {
this.tobacco = false;
this.paper = false;
this.match = false;
}
synchronized void getResources(int threadno){
// if thread has tobacco
if (threadno==0) {
// while paper and match are false
while(!paper || !match){
try{ wait(); } catch(InterruptedException e){}
}
paper = false;
match = false;
System.out.println("Thread "+threadno+" took paper and match...");
}
// if thread has paper
else if (threadno==1) {
// while tobacco and match are false
while(!tobacco || !match){
try{ wait(); } catch(InterruptedException e){}
}
match = false;
tobacco = false;
System.out.println("Thread "+threadno+" took match and tobacco...");
}
// if thread has match
else {
// while tobacco and paper are false
while(!tobacco || !paper){
try{ wait(); } catch(InterruptedException w){}
}
tobacco = false;
paper = false;
System.out.println("Thread "+threadno+" took tobacco and paper...");
}
notify();
}
synchronized void makeAvailable(int material){
while(tobacco || paper || match){
try{ wait();} catch(InterruptedException e){}
}
// if we're not putting down tobacco then
if (material==0) {
paper = true;
match = true;
}
// else if we're not putting down paper
else if (material==1) {
tobacco = true;
match = true;
}
// else if we're not puting down match
else {
tobacco = true;
paper = true;
}
notify();
System.out.println("Agent put new materials on table for "+material+"...");
}
// end of Resources class
}
// Agent class
class Agent extends Thread {
private Resources resources;
// default constructor
public Agent(Resources resources) {
this.resources = resources;
}
// Agent run() method
public void run() {
for(;;) {
resources.makeAvailable((int)(Math.random()*3));
}
}
// end of Agent class
}
// Smoker class
class Smoker extends Thread {
private int threadno;
private Resources resources;
// default constructor
public Smoker(int threadno,Resources resources) {
this.threadno = threadno;
this.resources = resources;
}
public void run(){
for(;;) {
resources.getResources(threadno);
}
}
// end of Smoker class
}
