I have the following 2 classes code that produce this result for instance:
Wainting for calculation to complete...
Calculator thread says HELLO!
T1 says that total is 10
Wainting for calculation to complete...
Wainting for calculation to complete...
Now threads are waiting but nobody is going to notify them.
How can I force the threads from T1 to T3 to run before the “Calculator thread” wake em up?
public class Calculator implements Runnable{
private int total;
public int getTotal() {
return total;
}
@Override
public void run() {
synchronized (this) {
for (int i = 0; i < 5; i++) {
total += i;
}
System.out.println(Thread.currentThread().getName() + " says HELLO!");
notifyAll();
}
}
}
import static java.lang.System.out;
public class Reader implements Runnable{
private Calculator c;
public Reader(Calculator calc) {
c = calc;
}
public Calculator getCalculator() {
return c;
}
public static void main(String[] args) {
Calculator calc = new Calculator();
Reader read = new Reader(calc);
Thread thread1 = new Thread(read);
Thread thread2 = new Thread(read);
Thread thread3 = new Thread(read);
thread1.setName("T1");
thread2.setName("T2");
thread3.setName("T3");
thread1.start();
thread2.start();
thread3.start();
Thread calcThread = new Thread(read.getCalculator());
calcThread.setName("Calculator thread");
calcThread.start();
}
}
@Override
public void run() {
synchronized (c) {
try {
out.println("Wainting for calculation to complete...");
c.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println(Thread.currentThread().getName() + " says that " + "total is " + c.getTotal());
}
}
}
Thread.join() may seem like an option in this particular situation. Since you have control of the
main()function and you know exactly when each thread is starting.A more general way to handle this situation is use a conditional variable and call the
c.wait()within a loop to check the condition variable.Basically add the
isFinishedfield in theCalculatorclass :public class Calculator implements Runnable { ... public volatile boolean isFinished = false .. ..Then you replace
c.wait()with :... while (!c.isFinished) { c.wait(); } ...Finally in the `run() method of your Calculator class after calculating total, set the isFinished field
.... for(int i = 0; .... total = += i; } c.isFinished = true ....