java - 线程notifyAll()

标签 java multithreading

给定一个线程有多种状态: 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 线程还将检查此标志,并仅在 isCalculatedfalse 时等待。

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/

相关文章:

javax.json 对象具有相同的方法,但它们不是公共(public)接口(interface)的实现。怎么投?

java - ORA-01810 : format code appears twice : jdbctemplate

java - Android - 如何通过文件名获取文件?

multithreading - 合并 channel 中的项目

java - 线程跳过一些迭代

Java Swingworker 不能与 swt 一起使用吗?

java - 通过配置文件初始化 "singleton"是否合适?

java - 如何在 entitymanager createNativeMethod 中回滚

java - 当未使用时,对象是否在编译时被优化?

C++11:使用成员函数和 this 在对象中启动线程