Java 使用 wait 和 notifyAll 时程序冻结

Java program freezes when using wait and notifyAll

我试图深入了解 wait 和 notifyAll 的工作原理,但遇到了障碍。

本程序下载一个长文本文档,启动多个线程统计字符数,然后输出统计总数。

我正在使用 wait 和 notifyAll 来控制线程执行,以便它们按字母顺序完成。这是代码。我将接着解释这个问题。

public class Test {

    public static void main(String[] args) {
  //code that reads in the data

LongTask a = new LongTask(buffer, 'a', "Thread_a", 0);
    a.start();

LongTask b = new LongTask(buffer, 'b', "Thread_b", 1);
    b.start();

//Repeat code for all other characters

a.join();

System.out.println("Alphabet count is: " + SharedResults.getResults());

LongTask class 包含构造函数和 运行()

public class LongTask extends Thread {
//Instance variables created here

//LongTask constructor
public LongTask (StringBuffer buffer, char target, String name, int turn)
{
    super(name);
    this.sharedData = sharedData;
    inputData = buffer;
    this.target = target;   
    this.turn = turn;
}


//Run method iterates through input data and counts matching characters, 
//then calls addToResults
public synchronized void run()
{
    //Thread t = Thread.currentThread();
    String name = this.getName();
    int runTurn = this.turn;
    System.out.println(name + " running - Turn " + runTurn);
    Integer count = 0;
    for (int i = 0; i < inputData.length(); i++) {
        if (inputData.charAt(i) == target) {
        count ++;   
        }
    }
    ResultsEntry newResult = new ResultsEntry(count, target);
    SharedResults.addToResults(newResult, turn);
    }
}

SharedResults class 将结果添加到 Array。 addToResults 方法执行此操作并控制同步。

public class SharedResults extends Thread{
//Code that creates array
//Code for SharedResults constructor

public synchronized static void addToResults(ResultsEntry newResult, int turn)
{   
    Integer resultsCount =  newResult.getCount();
    char resultsTarget = newResult.getTarget();
    Thread t = Thread.currentThread();

    /*
     * Turn number is compared to the size of the results array to control the
     * order of execution. 
     */
    while (turn != results.size()){ 
        try {
            System.out.println("Wait printout");
            t.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    } 
    System.out.println(t.getName() + " is adding " + newResult);
    SharedResults input = new SharedResults(resultsCount, resultsTarget);
    System.out.println("Cumulative Results are " + results);    
    t.notifyAll();      
    }

这是我在调试中看到这一步时所看到的。 - 输入执行,所有 LongTask 线程启动

(Thread_a应该是第一个执行addToResults的线程)

-一些线程(不是 Thread_a)命中了 addToResults 的 while 评估并且不继续

-Thread_a 命中 while 评估并完全执行。 (现在应该轮到Thread_b了)

-Thread_e 执行 "Wait printout" (只是一个调试功能,告诉我线程何时等待)然后程序挂起。

在我看来我没有正确设置等待。在我添加到 sysout 之前,该程序实际上(或看起来)正常工作。知道这里发生了什么吗?

回答我自己的问题,

中对此进行了介绍

问题在于 notifyAll() 会通知所有 该对象的 正在等待的线程。因为我在每个线程上调用 wait(),来自另一个线程的 notifyAll() 没有通知任何其他线程。

按照链接 post 的建议,我创建了一个静态同步对象并调用了该对象的 wait 和 notify 方法。生成的代码如下所示: private static final Object LOCK = new Object();

public static void addToResults(ResultsEntry newResult, int turn)
{   
    Integer resultsCount =  newResult.getCount();
    char resultsTarget = newResult.getTarget();
    Thread thread = Thread.currentThread();

    /*
     * Turn number is compared to the size of the results array to control the
     * order of execution. 
     */
    synchronized (LOCK){
        while (turn != results.size()){
            try {
                System.out.println(thread.getName() + " is waiting");
                LOCK.wait();
                } catch (InterruptedException e) {}
        }
            System.out.println(thread.getName() + " is adding " + newResult);
            SharedResults input = new SharedResults(resultsCount, resultsTarget);
            System.out.println("Cumulative Results are " + results);    
            LOCK.notifyAll();   
        }
        }

感谢所有评论的人!