给定一个线程有多种状态: Activity 、可运行、运行、等待和终止。 notifyAll() 方法假设将所有正在“等待”对象锁的线程重新置于“可运行”状态,在该状态下可以选择该对象作为下一个运行对象。 以下示例实例化并启动 3 个 Reader 线程,这些线程进入等待状态(wait() 方法),直到释放“calc”对象的锁。计算对象线程被实例化并在此之后启动,它会添加一些数字,然后是notifyAll()。
我的问题是,为什么 calc 线程每次都不通知所有 Reader 线程?当我在计算机上运行它时,它时好时坏。
public class Reader extends Thread{
Calculator c;
public Reader(Calculator calc){
c=calc;
}
public void run(){
synchronized(c){
try{
System.out.println("Waiting for calculation...");
c.wait();
}catch(InterruptedException e){}
System.out.println("Total is: "+c.total);
}
}
public static void main(String[] args){
Calculator calc = new Calculator();
new Reader(calc).start();
new Reader(calc).start();
new Reader(calc).start();
new Thread(calc).start();
}
}
class Calculator implements Runnable{
int total;
public void run(){
synchronized(this){
for(int i =0; i<100; i++){
total+=i;
}
notifyAll();
}
}
}
最佳答案
执行多个线程时,不保证线程的执行顺序。
在您的情况下,即使在任何 Reader
线程进入之前,Calculator
线程也可能完成其循环并调用 notifyAll()
可运行状态。因此所有Reader
都会继续等待,并且永远不会打印total
。
为了避免这种情况,在此特定示例中,您可以在 Calculator
中使用另一个标志 isCalculated
,并在计算完成后设置此标志。 Reader
线程还将检查此标志,并仅在 isCalculated
为 false
时等待。
class Reader extends Thread {
Calculator c;
public Reader(Calculator calc) {
c = calc;
}
public void run() {
synchronized (c) {
try {
System.out.println("Waiting for calculation...");
if (!c.isCalculated) { // wait only if calculation is not done
c.wait();
}
} catch (InterruptedException e) {
}
System.out.println("Total is: " + c.total);
}
}
}
class Calculator implements Runnable {
int total;
boolean isCalculated;
public void run() {
synchronized (this) {
for (int i = 0; i < 100; i++) {
total += i;
}
isCalculated = true; // set flag to mark that computation is complete
notifyAll();
}
}
}
关于java - 线程notifyAll(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38627045/