我正在阅读OCA / OCP Java SE 7程序员I& II学习指南,我被困在一个例子:
package threads;
class Totalizer implements Runnable
{
int total = 0;
public void run(){
synchronized(this){
for(int i = 0; i < 100; i++){
total += i;
}
notifyAll();
}
}
}
class Tester extends Thread
{
Totalizer t;
public Tester(Totalizer tot){t = tot;}
public void run(){
synchronized(t){
try {
System.out.println("Waiting for calculation...");
t.wait();
} catch (InterruptedException e) {}
System.out.println(t.total);
}
}
public static void main(String[] args){
Totalizer t = new Totalizer();
new Tester(t).start();
new Tester(t).start();
new Tester(t).start();
}
}
//
当我运行main()时,它会打印:
waiting for calculation...
waiting for calculation...
waiting for calculation...
没有任何反应,没有计算,没有。我无法弄清楚这段代码有什么问题。
答案 0 :(得分:2)
两点。
最明显的一点是你永远不会启动Totalizer
runnable,因此永远不会发出notifyAll调用。你需要一行
new Thread(t).start();
main
方法中的某处。但即使你这样做,它也无法可靠地工作,因为wait
调用可以在<{em> notifyAll
调用之后调用。它也可能过早打印输出,因为wait
调用也可以在没有notifyAll
的情况下唤醒。
Javadoc for Object.wait()
描述了您需要做的事情:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
因此,如果要正确使用它,就不能像这样调用Object.wait。这是因为:
在您的情况下,您需要一个可以检查的条件变量。例如,您可以像这样更改代码:
class Totalizer implements Runnable
{
int total = 0;
boolean calculationComplete; // Condition to check in wait()
public void run() {
for(int i = 0; i < 100; i++) {
total += i;
}
synchronized (this) {
// Indicate condition for wait() is now true
calculationComplete = true;
notifyAll();
}
}
}
class Tester extends Thread
{
Totalizer t;
public Tester(Totalizer tot){t = tot;}
public void run(){
synchronized(t) {
System.out.println("Waiting for calculation...");
// Loop, terminate when condition is true
while (!t.calculationComplete) {
try {
t.wait();
} catch (InterruptedException e) {}
}
System.out.println(t.total);
}
}