Java wait() 不会被notify() 唤醒 [英] Java wait() does not get waked by notify()

查看:21
本文介绍了Java wait() 不会被notify() 唤醒的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我已经调试代码一整天了,但我看不出哪里出错了.

Hallo I've been debugging my code for a whole day already, but I just can't see where could be wrong.

我在主线程上使用 SerialPortEventListener,在工作线程中,我有一个客户端套接字与服务器通信.因为在这个工作线程到达 return 之后,我仍然需要在主线程中完成一些总结工作,我想创建一个伪线程",在主线程中等待,直到它从侦听器得到通知onEvent 方法.

I use SerialPortEventListener on a main thread, in a working thread I have a client socket communicating to a server. Since after this working thread reach return, I still need some wrap up work done in the main thread, i want to create a "pseudothread" that wait in the main thread until the it is notified from the listener onEvent method.

但是这个伪线程似乎永远在等待.

but this pseudothread seems to be waiting forever.

我检查了锁定的线程 pseudoThread,它们在 Runnable 和 Listener 类中应该具有相同的对象 ID.

I checked the locked thread pseudoThread, they should have the same object id in the Runnable and in Listener class.

PseudoThread waiting"被显示,但PseudoThread唤醒从未显示.

"PseudoThread waiting" got displayed, but PseudoThread awake is never showed.

控制台输出显示:伪线程等待....错误通知的伪线程.

Console output shows: PseudoThread waiting .. .. false notified pseudothread.

PS 如果我用 public final Object lock = new Object(); 在 Main 类中创建一个锁并用 替换所有 main.pseudoThreadmain.lock,我得到 java.lang.IllegalMonitorStateException.

PS if I create a lock in Main class with public final Object lock = new Object(); and replace all main.pseudoThread with main.lock, I get java.lang.IllegalMonitorStateException.

private class Pseudo implements Runnable{
    Main main;
    public Pseudo(Main main) {
        this.main = main;
    }

    @Override
    public void run() {
        synchronized(main.pseudoThread){
            try {
                System.out.println("PseudoThread waiting");
                main.pseudoThread.wait();
                System.out.println("PseudoThread awake");
            } catch (InterruptedException e) {
                e.printStackTrace();
                return;
            }
        }

    }

}

在主方法中:

public static void main(String[] args) {
    Main main = new Main();
    main.initArduino();
    //more code. including starting the working thread
    main.pseudoThread = new Thread(main.new Pseudo(main));
        main.pseudoThread.start();
        try {
            main.pseudoThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
}
private void initArduino() {
    arduino = new Arduino(this);
    if(!arduino.initialize())
        System.exit(1);
}

在侦听器类中(也在主线程中运行)

and in the listener class (which also runs in main thread)

//class constructor;
public Arduino(Main Main){
    this.main = Main;
}
//listening method
public void serialEvent(SerialPortEvent oEvent){
    //some code to interract with working thread.
    record();

}
private void record(){
        synchronized(main.pseudoThread){
            main.pseudoThread.notify();
            System.out.println("notified pseudothread.");
        }
}

推荐答案

正如 james 所建议的那样,它可能会丢失通知案例,或者可能是.. 两个线程 1- 您的主线程和 2- 伪线程正在等待同一个线程实例锁(main.pseudoThread)(主线程通过调用join方法等待同一个锁).现在您正在使用通知从 join 方法中唤醒主线程,而不是唤醒主线程等待你的伪.要检查第二种情况,请尝试在记录中调用 notifyall 这将确认第二种情况或将裁定这种可能性.

As suggested by james it could be lost notification case or it could be that.. Two Threads 1- Your Main Thread and 2- Pseudo thread Are waiting on the same Thread Instance Lock (main.pseudoThread)( Main thread waits on the same lock by calling join method). Now you are using notify which wakes the Main thread from join method and not the one waiting in your Pseudo. To check for the second case try calling notifyall in record this will either confirm the second case or will rule this possibility.

无论如何,请重构您的代码,不要在 Thread 实例上使用同步,这是不好的做法.使用 ReentrantLock 或 CoundDownLatch 什么的.

Anyways please refactor your code not to use synch on Thread instance its bad practice. Go for ReentrantLock or CoundDownLatch something.

这篇关于Java wait() 不会被notify() 唤醒的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆