当前位置: 首页 > 知识库问答 >
问题:

程序停止:wait()和notify()

端木阳荣
2023-03-14

我试图做到这一点:创建两个不同的线程,一个打印奇数,一个打印偶数。一旦一个线程打印出一个数字,它就必须等待另一个线程,以此类推,这是一个接一个的。

为了实现这一点,我将使用synchronized block以及wait()和notify()。

我正在创建一个类,该类的对象将用于传递给两个线程中的同步块。

--

package com.vipin.multithread.variousdemos;

    public class SyncObject {

        public SyncObject () {  

        }
}
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...");
}
}

---

SyncObject作为参数传递给main中的这些不同线程。

但是,此程序会停止,即仅执行第一条语句,然后它将永远等待:

奇数是---

在主线程中,偶数为---

我无法理解为什么这个程序会一直等待,我使用的是我们调用synchronized()、wait()和notify()的同一个对象。根据我的理解,它应该是有效的,但不确定为什么不起作用。

任何关于这件事为什么永远都在等待的线索。

我在代码中做了一些更改,更新,它工作正常。

我仍然有些怀疑。即使线程没有锁定监视器,也会像我更新代码后的情况一样,调用通知()。

事件的顺序:

奇数线程首先被执行,然后它调用等待()

即使是线程也会运行、打印消息并调用notify()

当线程调用notify()时,此时它拥有监视器,所以当它调用notify()时,它仍然拥有监视器吗?

现在,偶数线程调用notify()后,奇数线程会收到通知,因此它会从Hibernate点开始执行。它正在执行一些操作并调用notify(),在这一点上,我假定奇数线程没有拥有监视器,它调用notify()。所以,我的问题是,无论线程是否拥有监视器,notify()的工作原理是否相同?

只有当你编写代码时,你才能真正理解这一点。我读了这本书,我觉得我明白了一切,似乎我又回到了原点!

共有1个答案

哈宪
2023-03-14

这里的问题很简单,两个线程都直接进入等待。线程1获取所以,打印值然后等待。线程2然后获取所以,打印值然后等待。所以两人都在睡觉,因为没有人通知他们。所以,一个简单的修复方法是在so.wait()之前执行so.notify()。那他们就不会无限等待。

编辑

奇数线程启动,执行

当偶数线程调用notify时,奇数线程唤醒

如果偶数线程没有调用通知,那么奇数线程将继续Hibernate。偶数线程会等待

留档也提供了类似的解释。我希望这能消除你的疑虑。

 类似资料:
  • 我运行我的Android应用程序(基于Java),它可以工作。接下来,我添加到我的应用程序代码: FirebaseFirestore fdb=FirebaseFirestore。getInstance(); 这是我从Android官方网站上得到的代码https://firebase.google.com/docs/firestore/quickstart 应用程序运行,但接下来运行的设备显示消息“

  • 我们为Azure Portal中托管的Web应用程序安装了应用程序Insights。

  • 我试图重新创建Connect四,我成功了。但我想通过频繁地切换颜色,给玩家一个获胜的四张光盘在哪里的指示。我对线程和编程中的时间概念是新的。 我也成功地给了用户这个指示,但是在关闭应用程序之后,控制台仍然会给出输出,也是在使用SetonCloserEquest时。 代码如下:

  • 问题内容: 我有一个侦听端口的简单TCP服务器。 我先将其启动,然后在Mac上使用Ctrl + Z将其关闭。当我尝试再次运行它时,出现以下错误消息: 我是否以错误的方式关闭程序?如何防止这种情况发生? 问题答案: 要结束程序,您应该使用+ 。如果这样做,它会发送,从而允许程序正常结束,并与正在侦听的任何端口解除绑定。 另请参阅:https : //superuser.com/a/262948/48

  • 我们在Tomcat 6上有一个Spring 3 Web应用程序,它通过(主要用于每天晚上运行的作业)使用了几个计划服务。现在看来,有时(很少,也许是两个月左右一次)调度程序线程会停止工作,因此在接下来的晚上不会执行任何作业。在我们的日志文件中没有异常或日志条目。 有人知道为什么会发生这种情况吗?或者如何获得关于这个问题的更多信息? 有没有办法在应用程序中检测到这种情况并重新启动调度程序? 目前,我

  • 我有一个简单的控制台应用程序,有时需要执行图形操作,对于那些我使用JavaFx框架(有一些功能,我需要像css样式的文本)我只是生成一些形状和文本到一个隐藏的场景,然后保存在文件中仅此而已, 我知道要使用JavaFx,我必须将图形操作传递给JavaFx线程,但是当一切都完成后,我必须关闭应用程序(几个小时后),这个JavaFx线程仍然保持打开...我真的不想强行退出System.exit(),因为