调用 wait() 不会停止正确的线程
Calling wait() doesn't stop the correct thread
我是 java 中的多线程新手。我正在尝试 运行 一个可以模拟多个 "Writers" 将数据作为输出写入的程序。
我希望所有的作者都在某个时候停下来,所以我正在对他们调用 wait(),但它不起作用。我知道问题出在哪里,但我不知道为什么会发生。
public void run() {
ExecutorService executor = Executors.newFixedThreadPool(nbOfWriters);
try {
// Create a list with all the writers that should run at the same time
Writer[] writers = new Writer[nbOfWriters];
for (int i = 0; i < nbOfWriters; i++) {
writers[i] = new Writer(i);
executor.execute(writers[i]);
}
/*
Expected outcome:
start every writer -> wait 3 seconds
pause every writer -> wait 3 seconds
run every writer -> wait 3 seconds
end
*/
TimeUnit.SECONDS.sleep(3);
for (Writer writer : writers) {
synchronized (writer) {
System.out.println("HERE 1");
writer.wait();
System.out.println("HERE 2");
}
}
TimeUnit.SECONDS.sleep(3);
for (Writer writer : writers) {
synchronized (writer) {
writer.notify();
}
}
Thread.sleep(3);
// End of the test
for (Writer writer : writers) writer.end();
}
catch (InterruptedException ex) {
System.out.println(ex.getMessage());
}
finally {
try {
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
}
catch (InterruptedException ex) {
ex.getMessage();
}
finally {
executor.shutdownNow();
}
}
}
作家们只是把东西写成输出(这里不重要)。
我添加了打印语句 "HERE 1" 和 "HERE 2" 来显示程序失败的地方。基本上"HERE 2"是永远达不到的。
理论上应该发生的情况是我将数据写入 3 秒,然后 3 秒没有数据,然后再次将数据写入输出。
实际输出为:
东西被写为输出 3 秒。
"HERE 1" 已打印。
内容继续显示为输出,没有暂停,没有 "HERE 2" 并且程序永远不会停止。
在我看来 wait() 停止了错误的线程。
wait()
的文档说:
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
所以主线程是在 "HERE 2"
之前等待的,因为它一直在等待,所以它永远无法到达 notify
。
我不确定是否有明确的方法来做你想做的事(告诉另一个线程等待)。有一些已弃用的 API 很好地解释了为什么你不应该使用它们:https://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Shouldn't writer.wait()
call wait in the specific writer thread like other methods would?
没有
声明,writer.wait();
使用 writer
对象作为 monitor。监视器应该以非常特定的方式使用*。它允许一个线程等待某个(可能未知的)其他线程完成一项任务。想要等待的线程通过调用 o.wait();
一个线程无法使使另一个线程调用一个函数。一个线程根本无法 让 另一个线程做任何事情。线程执行它们正在执行的代码告诉它们做的事情,并且在一个设计良好的程序中,该代码告诉它们彼此合作。线程 A 请求 线程 B 做某事有多种方法,但要由 你 编写在线程 A 中运行的代码来完成询问,由您编写在线程 B 中运行的代码,该代码可以识别何时被询问,然后执行任何操作。
* 请参阅 Oracle "guarded block" tutorial。
笔记!本教程没有使用 "monitor" 这个词,但它讨论的是相同的模式。
我是 java 中的多线程新手。我正在尝试 运行 一个可以模拟多个 "Writers" 将数据作为输出写入的程序。
我希望所有的作者都在某个时候停下来,所以我正在对他们调用 wait(),但它不起作用。我知道问题出在哪里,但我不知道为什么会发生。
public void run() {
ExecutorService executor = Executors.newFixedThreadPool(nbOfWriters);
try {
// Create a list with all the writers that should run at the same time
Writer[] writers = new Writer[nbOfWriters];
for (int i = 0; i < nbOfWriters; i++) {
writers[i] = new Writer(i);
executor.execute(writers[i]);
}
/*
Expected outcome:
start every writer -> wait 3 seconds
pause every writer -> wait 3 seconds
run every writer -> wait 3 seconds
end
*/
TimeUnit.SECONDS.sleep(3);
for (Writer writer : writers) {
synchronized (writer) {
System.out.println("HERE 1");
writer.wait();
System.out.println("HERE 2");
}
}
TimeUnit.SECONDS.sleep(3);
for (Writer writer : writers) {
synchronized (writer) {
writer.notify();
}
}
Thread.sleep(3);
// End of the test
for (Writer writer : writers) writer.end();
}
catch (InterruptedException ex) {
System.out.println(ex.getMessage());
}
finally {
try {
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
}
catch (InterruptedException ex) {
ex.getMessage();
}
finally {
executor.shutdownNow();
}
}
}
作家们只是把东西写成输出(这里不重要)。 我添加了打印语句 "HERE 1" 和 "HERE 2" 来显示程序失败的地方。基本上"HERE 2"是永远达不到的。
理论上应该发生的情况是我将数据写入 3 秒,然后 3 秒没有数据,然后再次将数据写入输出。
实际输出为: 东西被写为输出 3 秒。 "HERE 1" 已打印。 内容继续显示为输出,没有暂停,没有 "HERE 2" 并且程序永远不会停止。
在我看来 wait() 停止了错误的线程。
wait()
的文档说:
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
所以主线程是在 "HERE 2"
之前等待的,因为它一直在等待,所以它永远无法到达 notify
。
我不确定是否有明确的方法来做你想做的事(告诉另一个线程等待)。有一些已弃用的 API 很好地解释了为什么你不应该使用它们:https://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Shouldn't
writer.wait()
call wait in the specific writer thread like other methods would?
没有
声明,writer.wait();
使用 writer
对象作为 monitor。监视器应该以非常特定的方式使用*。它允许一个线程等待某个(可能未知的)其他线程完成一项任务。想要等待的线程通过调用 o.wait();
一个线程无法使使另一个线程调用一个函数。一个线程根本无法 让 另一个线程做任何事情。线程执行它们正在执行的代码告诉它们做的事情,并且在一个设计良好的程序中,该代码告诉它们彼此合作。线程 A 请求 线程 B 做某事有多种方法,但要由 你 编写在线程 A 中运行的代码来完成询问,由您编写在线程 B 中运行的代码,该代码可以识别何时被询问,然后执行任何操作。
* 请参阅 Oracle "guarded block" tutorial。
笔记!本教程没有使用 "monitor" 这个词,但它讨论的是相同的模式。