Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java等待/通知-未唤醒线程_Java_Multithreading_Wait_Notify - Fatal编程技术网

Java等待/通知-未唤醒线程

Java等待/通知-未唤醒线程,java,multithreading,wait,notify,Java,Multithreading,Wait,Notify,我正试着做一个小练习来习惯等待/通知。 我试图做的是简单地启动一个线程,然后让它在等待中休眠,然后在通知中唤醒它,多次 我的代码是: 公共类简单{ 静态最终线程mainThread=Thread.currentThread(); 公共静态void main(字符串[]args)引发InterruptedException{ PrintThread打印机=新的PrintThread(0); printer.start(); 已同步(主线程){ System.out.println(“等待打印机启动

我正试着做一个小练习来习惯等待/通知。 我试图做的是简单地启动一个线程,然后让它在等待中休眠,然后在通知中唤醒它,多次

我的代码是:

公共类简单{
静态最终线程mainThread=Thread.currentThread();
公共静态void main(字符串[]args)引发InterruptedException{
PrintThread打印机=新的PrintThread(0);
printer.start();
已同步(主线程){
System.out.println(“等待打印机启动时主休眠”);
mainThread.wait();
System.out.println(“主唤醒”);
对于(int i=0;i<1000;i++){
同步(打印机){
System.out.println(“添加的数值”+i);
printer.numToPrint=i;
System.out.println(“主唤醒打印机”);
printer.notifyAll();
System.out.println(“主睡眠”);
mainThread.wait();
System.out.println(“主唤醒”);
}
}
}
}
}
类PrintThread扩展线程{
公共int numToPrint=-1;
公共打印线程(int numToPrint){
this.numToPrint=numToPrint;
}
@凌驾
公共同步的无效运行(){
System.out.println(“打印机已启动”);
while(true){
试一试{
已同步(Simple.mainThread){
System.out.println(“打印机唤醒主”);
Simple.mainThread.notifyAll();
}
System.out.println(“打印机休眠”);
等待();
System.out.println(“打印机唤醒”);
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(“printing num”+numToPrint);
}
}
}
我希望事情会像这样发展

main sleeping while waiting for printer to be started
printer started
printer waking up main
printer sleeping
main woke up
added num 0
main waking up printer
main sleeping
printer woke up
printing num 0
printer waking up main
printer sleeping
main woke up
added num 1
...
而是:

main sleeping while waiting for printer to be started
printer started
printer waking up main
printer sleeping
main woke up
added num 0
main waking up printer
main sleeping
所以。。。好像notify没有唤醒打印机线程

它不应该是一个死锁,因为通过等待我可以解除所有的锁定,因此不应该对打印机有任何锁定,并且打印机应该能够唤醒并打印

我做错了什么?

很可能是在再次调用Print calls wait()之前调用了notifyAll()调用。问题在于您对等待和通知的依赖,所有调用都是按照您希望的顺序进行的。这是两个不同的执行线程,所以当然这不是保证,因此您得到的是您已经得到的

实现这一点的更好方法是创建一个公共的第三共享对象,两个线程都可以获得锁定。这将使两个线程在等待访问此对象时同步


此外,您还应该阅读Thread.wait、notify和notifyAll的Javadocs。如果/当您这样做时,您将看到您永远不应该在线程上调用这些方法,因为它们用于执行thread.join(不仅如此,还包括我的“声名远播”)我相信这是我多年前的错误请求,当它不在JavaDoc中时,它被添加到JavaDoc中。可能是其他人,但它发生在我请求之后:)

属性:调用wait()释放锁(它正在监视)并进入等待状态。它在同一对象上等待notify()或notifyAll()。一旦notify()或notifyAll()在CPU中得到调度,它将在恢复之前再次获取锁

当您在main方法中第一次执行“synchronized(mainThread)”时,它基本上锁定了“mainThread”类对象。调用mainThread.wait()时,mainThread处于等待状态(等待有人在mainThread类对象上调用notify或notifyAll)

此时,PrintThread可能会获得CPU。这是“synchronized(Simple.mainThread)”被调度并锁定“Simple.mainThread”并通知所有等待“Simple.mainThread”的线程的时候。在这个块完成后,PrintThread释放“Simple.mainThread”锁

此时,主线程将再次尝试获取“主线程”上的锁,然后从调用wait的位置恢复。因为此时未获取“mainThread”锁,所以主线程获取锁并打印“mainwakeup”

现在,这里遇到了for循环。 记住:这里已经获得了对“mainThread”类对象的锁定

现在在for循环内部,它获得了对“printer”对象的锁定。执行一些计算并调用“printer.notifyAll()”,所有等待“printer”对象的线程都将得到通知

**这里要记住的一点是:由于代码光标仍在“synchronized(printer)”内,所以尚未释放对“printer”对象的锁定**

向前看,将打印“main sleeping”,然后调用“mainThread.wait()”。这将尝试获取已获取的“mainThread”上的锁(如上所述,其中“记住:”在块中),并被卡住,因为此后没有线程在“mainThread”上进行通知,“synchronized(printer)”块永远不会结束,即即使在调用NotifyAll()之后,“printer”对象上的锁也永远不会解除

尝试在开始时在main方法中添加以下代码,以测试上述场景。

synchronized (mainThread) {
            synchronized (printer){
                System.out.println("Before");
                mainThread.wait();
                System.out.println("After");
            }
解决方案:
在“printer.notifyAll()”之后关闭“synchronized(printer)”块,以便在通知之后和获取“main thread”之前释放“printer”锁。

Mhh。。。这是有道理的,如果主调用在打印机进入睡眠前通知,那么整个程序将被阻止。但是输出说等待首先被调用。。。那么,是否有可能等待开始执行,但在通知开始之前不结束执行?@FedericoSpece,正如我所说,你这样做是错误的,你永远不会把它发送给w