Java 了解多线程等待和通知
我正在学习多线程,并试图理解如何使用对象类的wait和notify方法。我已经通过了这个链接,并编写了以下程序 侍者Java 了解多线程等待和通知,java,multithreading,Java,Multithreading,我正在学习多线程,并试图理解如何使用对象类的wait和notify方法。我已经通过了这个链接,并编写了以下程序 侍者 public class Waiter implements Runnable { private Message m; public Waiter(Message m) { this.m = m; } public void run() { String name = Thread.currentThread()
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();
}
}
}
}
试验
当我执行程序时,它有时正确地终止,有时无限期地等待,有时一个线程终止,另一个线程无限期地等待。谁能告诉我这里怎么了
另外,我还想知道一些等待和通知方法的实时应用示例。当您执行等待时,最佳实践是在一个带条件的while循环中执行。可能会出现这样的情况,线程将通知,然后其他线程进入等待状态。因此线程将始终处于等待状态 修改代码:
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(name + " thread waiting for message");
synchronized (m) {
try {
while (m.getText() == null) {
m.wait();
}
System.out.println(name + " " + m.getText());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name + " thread waiting for message");
}
}
public class Notifier implements Runnable {
private Message m;
public Notifier(Message m) {
this.m = m;
}
public void run() {
synchronized (m) {
m.setText("hello");
m.notifyAll();
}
}
}
public class WaitNotifyTest {
public static void main(String[] str) {
Message m = new Message();
new Thread(new Waiter(m), "t1").start();
new Thread(new Waiter(m), "t2").start();
new Thread(new Notifier(m)).start();
}
}
我认为问题在于通知程序类的同步块中的Thread.sleep(2000)。一旦我将其移出同步块,程序就会始终正确终止。有人能告诉我这里有什么不同吗?假设
通知程序线程首先运行,并进入同步(m)
部分<代码>服务员
线程无法进入此分区,直到通知程序
离开它。但在离开时,m.notifyAll()
已执行。因此,当water
进入该部分并执行m.wait()
时,它将永远等待:之后没有人会通知线程。通过将Thread.sleep(2000)
移动到分区之外,您使给定场景变得不太可能:而Notifier
在关键分区之外休眠,当我将Thread.sleep移到synchronized块之外并且程序正确终止时,water
很有可能首先进入该部分。或者,我按照你的建议,将Thread.sleep移回synchronized并添加了循环,程序很好地终止了。我无法理解在同步块内部和外部使用Thread.sleep有什么区别。使用Thread sleep时,它总是暂停当前线程的执行,线程睡眠不会丢失当前线程获得的任何监视器或锁。因此,wait在通知程序之后执行的可能性很高。@gati sahu-因为代码使用notifyAll()不会调用所有等待的线程。此外,张贴的代码对我来说没有阻塞。我能想到的唯一可能性是,如果通知是在线程等待()之前处理的。@gatisahu很抱歉,我不明白。我不熟悉多线程。我只有理论知识。你能详细解释一下吗?
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(name + " thread waiting for message");
synchronized (m) {
try {
while (m.getText() == null) {
m.wait();
}
System.out.println(name + " " + m.getText());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name + " thread waiting for message");
}
}
public class Notifier implements Runnable {
private Message m;
public Notifier(Message m) {
this.m = m;
}
public void run() {
synchronized (m) {
m.setText("hello");
m.notifyAll();
}
}
}
public class WaitNotifyTest {
public static void main(String[] str) {
Message m = new Message();
new Thread(new Waiter(m), "t1").start();
new Thread(new Waiter(m), "t2").start();
new Thread(new Notifier(m)).start();
}
}