一个简单的等待()& notify()示例 - 不起作用

时间:2015-12-13 19:52:46

标签: java wait

我尝试编写一个演示远程控制器操作的简单示例。 输入正在通过控制台接受,并且正在相应地打印消息。

两个线程都运行无限循环:主线程等待通知,而另一个线程等待控制台输入。

我想知道如何修复它。问题是通知不会停止等待:换句话说,打印“等待前”字样,但“等待后”字样不是。顺便说一句,如果没有while(true)循环,它可以正常工作(按下一个按钮)。

非常感谢

    public class MainTV {
    public static int lastRemoteCode = 0;   
    public static void main(String[] args){
        RemoteControllerThread remote = new RemoteControllerThread();
        remote.start();
        synchronized(remote){
            while(true){                    
                try {
                    System.out.println("before wait");
                    remote.wait();
                    System.out.println("after wait");
                    switch (lastRemoteCode){ //we use switch because there are many code options
                    case 0:
                        System.out.println("Error with remote button reading");
                        break;
                    case 3:
                        System.out.println("Volume Down button was pressed now!");
                        break;
                    case 4:
                        System.out.println("Volume Up button was pressed now!");
                        break;
                    }
                } catch (InterruptedException e) {                  
                    e.printStackTrace();
                }               

            }
        }
    }
}

和第二个类(模拟遥控器):

    import java.util.Scanner;
    public class RemoteControllerThread extends Thread{
    public void run(){
        synchronized(this){
            Scanner in = new Scanner(System.in); 
            while(true){
                System.out.println("Press a button in the remote please...");
                int code = in.nextInt();                
                MainTV.lastRemoteCode = code;
                System.out.println("before notify");
                notify();   
                System.out.println("after notify");
            }
        }
    }
}

3 个答案:

答案 0 :(得分:0)

我认为您的代码存在两个问题。

  1. 当主线程执行到达synchronized(remote)时,它可能无法继续,因为远程控制器线程(可能)已锁定remote对象。将remote.start()移至synchronized(remote)块。

  2. 为了让wait继续执行,您需要在notify之后释放对象锁。在线程中更改同步块,如:

  3. -

    public void run() {
        Scanner in = new Scanner(System.in); 
        while(true){
            System.out.println("Press a button in the remote please...");
            int code = in.nextInt();                
            MainTV.lastRemoteCode = code;
            System.out.println("before notify");
    
            synchronized(this) {
                notify();   
            }
    
            System.out.println("after notify");
        }
    }
    

答案 1 :(得分:0)

两个线程在同一个对象上同步,this引用与remote相同的对象,并且由于这两个同步块内部都有无限循环,因此会产生问题。其中一个线程将等待另一个线程完成,这从未发生过(因为无限循环)。

要解决此问题,您应该只同步需要同步的代码,例如wait()notify()来电。

答案 2 :(得分:0)

引用notify() JavaDoc:

  

在当前线程放弃对此对象的锁定之前,唤醒的线程将无法继续

您的遥控器永远不会放开锁定。如果您使用synchronized切换while,您的机会很小,但通常您远程会立即获得锁定。以下工作,例如:

class RemoteControllerThread extends Thread {
    public void run() {
        while (true) {
            synchronized (this) {
                Scanner in = new Scanner(System.in);
                System.out.println("Press a button in the remote please...");
                int code = in.nextInt();
                MainTV.lastRemoteCode = code;
                System.out.println("before notify");
                notify();
                System.out.println("after notify");
            }
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}