Java 程序停止:wait()和notify()
我试图做到这一点:创建两个不同的线程,一个打印奇数,一个打印偶数。一旦一个线程打印出一个数字,它就必须等待另一个线程,以此类推,这是一个接一个的 为了实现这一点,我将使用synchronized block以及wait()和notify() 我正在创建一个类,该类的对象将用于传递给两个线程中的同步块 代码如下: -->这是将传递给同步块的已使用对象Java 程序停止:wait()和notify(),java,multithreading,wait,synchronized,notify,Java,Multithreading,Wait,Synchronized,Notify,我试图做到这一点:创建两个不同的线程,一个打印奇数,一个打印偶数。一旦一个线程打印出一个数字,它就必须等待另一个线程,以此类推,这是一个接一个的 为了实现这一点,我将使用synchronized block以及wait()和notify() 我正在创建一个类,该类的对象将用于传递给两个线程中的同步块 代码如下: -->这是将传递给同步块的已使用对象 package com.vipin.multithread.variousdemos; public class SyncObject {
package com.vipin.multithread.variousdemos;
public class SyncObject {
public SyncObject () {
}
}
奇数螺纹:
偶数线程:更新
--->如代码所示,我创建了两个线程来打印偶数和奇数。我正在使用synchronized块,并传递类型==>SyncObject的对象
SyncObject作为参数传递给main中的这些不同线程
但是,此程序会停止,即仅执行第一条语句,然后它将永远等待:
以下是输出:
奇数为-->1
主线程中
偶数为-->2
我无法理解为什么这个程序会一直等待,我使用的是我们调用synchronized()、wait()和notify()的同一个对象。根据我的理解,它应该是有效的,但不确定为什么不起作用
任何关于这件事为什么永远都在等待的线索
更新:
我对代码做了一些修改,更新后效果很好
我仍然有些怀疑。即使没有锁定监视器,线程也会调用notify(),就像我更新代码后的情况一样
事件顺序:
首先执行奇数线程,然后调用wait()这里的问题只是两个线程直接进入等待。线程1获取
所以
,打印值然后等待。线程2然后获取,然后打印值并等待。所以两人都睡不着,因为没有人通知他们。因此,一个简单的修复方法是在So.wait()
之前执行So.notify()
。那他们就不会无限期地等待了
编辑
奇数线程启动、执行并等待。然后,即使是线程也会启动、执行、通知&然后等待。即使是线程也会在监视器上保持锁,直到它进入等待状态
当偶数线程调用notify时,奇数线程唤醒并轮询锁。一旦偶数线程进入等待状态(&释放锁),则奇数线程可以获得锁
如果偶数线程没有调用notify,那么奇数线程将继续休眠。偶数线程将等待并释放锁。没有线程轮询或试图获取锁,因此程序保持挂起状态
报告也提供了类似的解释。我希望这能消除你的疑虑 +1。不要忘记在OddThread
中添加if(index>=5){so.notify();return;}
,以唤醒EvenThread
。根据文档,wait()解锁监视器,然后停止调用它的线程的执行。这是基于我已经编码的。考虑,首先执行ODWTHOST,然后调用WAITE(),此时它将解锁监视器并停止执行,然后将执行线程,并在EngaveWAIT()上解锁监视器并停止执行。那么,在什么地方我们必须调用notify()。使用此模型,则我们没有任何机会通知()。我见过等待()的代码。。通知();其他线程也在等待()。。通知()。。我不知道我错过了什么!是的,wait()表示解锁监视器并停止执行。但是,这并不意味着其他线程开始执行。它们也处于“暂停”模式。Notify()告诉他们立即重新开始执行。通常,程序是在wait()语句最先出现的地方编写的,然后是notify(),然而,在执行时,您会发现一个线程进入wait(),而另一个线程跳过它&继续进入notify()。Wait()语句通常在某些条件下。谢谢@VineetRamachandran!我已经更新了问题,请看一看,我对notify()的行为w.r.t monitor/lock有疑问。1)在检查是否有需要等待的内容之前,不要调用wait
。2) 在某个地方,您必须存储您正在等待的东西,即下一个线程应该是哪个线程。没有它,线程就无法知道它是否应该等待,或者它是否应该工作。
package com.vipin.multithread.variousdemos;
public class OddThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int odd_nums[] = {1,3,5,7,9};
public OddThread(SyncObject so) {
t = new Thread(this,"Odd Thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
@Override
public void run() {
while (true) {
synchronized(so) {
System.out.println("Odd num is --->" + odd_nums[index]);
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
so.notify();
if(index>=5) {
return;
}
}
}
}
}
package com.vipin.multithread.variousdemos;
public class EvenThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int even_nums[] = {2,4,6,8,10};
public EvenThread(SyncObject so) {
t = new Thread(this, "Even thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
@Override
public void run() {
while(true) {
synchronized(so) {
System.out.println("Even num is --->" + even_nums[index]);
so.notify(); <-- Here we are notifying.
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
//so.notify(); <-- commented out.
if(index>=5) {
break;
}
}
}
}
}
package com.vipin.multithread.variousdemos;
public class EvenOddDemo {
public static void main(String[] args) throws InterruptedException {
SyncObject so = new SyncObject();
OddThread ot = new OddThread(so);
EvenThread et = new EvenThread(so);
System.out.println("\nIn main thread");
Thread.sleep(1000000000);
System.out.println("Exiting main thread...");
}
}