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();
}
}
感谢所有评论的人!
我试图深入了解 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();
}
}
感谢所有评论的人!