【发布时间】:2018-01-20 05:26:10
【问题描述】:
我正试图深入了解 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 类包含构造函数和 run()
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 类将结果添加到 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();
}
这是我在 Debug 中观看此步骤时看到的内容。 -Input 执行,所有 LongTask 线程启动
(Thread_a 应该是第一个执行 addToResults 的线程)
- 一些线程(不是 Thread_a)在 addToResults 的 while 评估中运行,并且不继续
-Thread_a 达到 while 评估并完全执行。 (现在应该轮到Thread_b了)
-Thread_e 执行“等待打印输出”(只是一个调试功能,告诉我线程何时等待),然后程序挂起。
在我看来,我没有正确设置等待。在我添加到 sysout 之前,该程序实际上(或看起来)正常工作。有什么想法吗?
【问题讨论】:
-
锁定在这里的工作方式令人困惑。如果您使用锁来保护共享数据结构(其中数据结构使用锁定来限制对其自身的访问)而不是由线程完成锁定,那么它可以减少混乱。
-
Re,“我正在使用 wait 和 notifyAll 来控制线程执行,以便它们按字母顺序完成。”这听起来像你在错误的方向开始你的旅程。任何时候你强迫线程以特定的顺序做事,你就颠覆了线程的概念,即并发(即,没有特定的顺序)做事。
-
public synchronized void run()---这总是是个坏主意。 -
如果
t引用Thread对象,调用t.wait()和t.notifyAll()可能会产生令人惊讶的结果。Thread类将t.wait()和t.notify()用于其自身目的。 -
我将 Thread 名称的变量更改为 thread,所以现在方法调用是 thread.wait() 和 thread.notifyAll()。这让每个线程至少执行 addToResults。看起来命中 wait() 的线程永远不会重新启动,即使在 thread_a 命中 notifyAll() 之后也是如此。
标签: java multithreading wait notify