哈罗我已经整天调试了我的代码,但是我只是看不出哪里出了问题。

我在主线程上使用SerialPortEventListener,在工作线程中,我有一个客户端套接字与服务器通信。
由于此工作线程到达return后,我仍然需要在主线程中完成一些包装工作,因此我想创建一个“伪线程”,在主线程中等待,直到从侦听器onEvent方法收到通知为止。

但是这个伪线程似乎一直在等待。

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

显示了“ PseudoThread等待中”,但从未显示PseudoThread唤醒。


  控制台输出显示:
  伪线程等待
  ..
  ..
  假通知伪线程。


PS,如果我在主类中使用public final Object lock = new Object();创建一个锁,并用main.pseudoThread替换所有main.lock,则会得到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);
}


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

//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方法)。
现在,您正在使用notify,它将Main线程从join方法唤醒,而不是一个
在你的Pseudo中等待。要检查第二种情况,请尝试在记录中调用notifyall,
确认第二种情况或将排除这种可能性。

无论如何,请重构您的代码,不要在Thread实例上使用synch是一种不好的做法。去ReentrantLock或CoundDownLatch一些东西。

09-05 00:34