【发布时间】:2018-05-14 02:52:03
【问题描述】:
我正在学习多线程,并试图了解如何使用 Object 类的等待和通知方法。我已经通过这个链接https://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example 并编写了以下程序
服务员
public class Waiter implements Runnable {
private Message m;
public Waiter(Message m) {
this.m = m;
}
public void run() {
String name = Thread.currentThread().getName();
System.out.println(t1 + " thread waiting for message");
synchronized (m) {
try {
m.wait();
System.out.println(t1 + " " + m.getText());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(t1 + " thread waiting for message");
}
}
通知器
public class Notifier implements Runnable {
private Message m;
public Notifier(Message m) {
this.m = m;
}
public void run() {
synchronized (m) {
try {
Thread.sleep(2000);
m.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试
public class WaitNotifyTest {
public static void main(String[] str) {
Message m = new Message("hello");
new Thread(new Waiter(m), "t1").start();
new Thread(new Waiter(m), "t2").start();
new Thread(new Notifier(m)).start();
}
}
当我执行程序时,它有时会正常终止,有时会无限期等待,有时其中一个线程终止,另一个线程无限期等待。谁能告诉我这里出了什么问题?
我还想知道一些实时应用等待和通知方法的例子。
【问题讨论】:
-
我认为问题出在 Notifier 类的同步块中的 Thread.sleep(2000) 上。一旦我将它移到同步块之外,程序总是会正确终止。谁能告诉我这里有什么区别?
-
假设
Notifier线程首先运行,并进入synchronized (m)部分。Waiter线程无法进入此部分,直到Notifier离开它。但在离开时,m.notifyAll()已经执行。因此,当Waiter进入该部分并执行m.wait()时,它将等待永远:此后没有人会通知线程。通过将Thread.sleep(2000)移动到该部分之外,您可以大大降低给定场景的可能性:虽然Notifier在在关键部分之外 休眠,但Waiter很有可能首先进入该部分。
标签: java multithreading