views:

113

answers:

1

I'm trying to write a program with 2 classes, a controller and a class that does a lot of computation. The controller creates a couple instances of the other class, then tells them all to start their calculations (in parallel). They each return when they are finished, and the controller resumes, and then, some time later, the controller passes them new data, and has them run the calculation again.
Ideally, I would be able to call start() with parameters, but that isn't possible, so the controller calls a method in the calculator that stores the data in a global, and then starts the calculation thread and returns, which works until I try to start the thread again, and it tells me the thread is dead. So I'm trying to make the run an infinite loop that just waits until it is notified, runs the calculations, stores the results in a global so the controller can retrieve them later, then resumes waiting. So something like:

//in controller:
Calculator calc=new Calculator();
calc.runCalculations(data);
while(calc.isCalculating()){
    //do nothing
}
System.out.println("results: "+calc.getAnswer());
calc.runCalculations(data2);

//in calculator:
public runCalculations(Data data){
    globalData=data;
    this.notify();
}
public void run(){
    while(true){
        synchronized(this){
            wait();
        }
        calculating=true;
        globalData=calculate(globalData);
        calculating=false;
    }
}
+3  A: 

You need to obtain the monitor on this before you call notify(). Also, when you call wait() you should do so in a loop that checks a condition to be certain that you did not experience a spurious wakeup.

public runCalculations(Data data){
    globalData=data;
    synchronized(this) {
        calculating=true;
        this.notify();
    }
}
public void run(){
    while(true){
        synchronized(this){
            calculating=false;
            while(!calculating) {
                wait();
            }
        }
        globalData=calculate(globalData);
    }
}

In general, most people would advise against using wait/notify and instead recommend you use an Executor or at the very least a BlockingQueue. But both of those would require you to redesign what you are currently thinking.

Tim Bender
Let me side with most people and advise against using the low-level thread synchronization primitives and use the concurrency package instead. At least take a look at BlockingQueue to see if you like it.
Thilo