2016-04-23 66 views
1

我不明白为什么我的代码无法正常工作。我期望第一个Thread等待4秒钟,让第二个Thread将共享布尔值“joy”设置为true,然后让第一个Thread打印出“Joy已经实现!”。试图让守卫块工作

当我运行代码,我得到这样的输出:

“没有喜悦然而......”

“通知喜悦”

然后它冻结起来,没有按”继续。如果我的理解是正确的,那么从我的notifyJoy()方法中调用的notifyAll()方法应该从其wait()中唤醒t1,然后,由于共享静态布尔变量joy现在成立,所以“Joy已经实现!应该打印到控制台。

我正在从甲骨文的“Java教程”第13章工作:这里是特定部分的链接:Java Tutorial Website。我要脱离他们的所作所为并举一个小例子,但我似乎无法弄清楚我做错了什么。任何帮助,将不胜感激。下面是我的代码,供大家参考完整副本:

public class JoyTime { 

    public static void main(String[] args) { 
     JoyRider j1 = new JoyRider(false); 
     JoyRider j2 = new JoyRider(true); 

     Thread t1 = new Thread(j1, "J1"); 
     Thread t2 = new Thread(j2, "J2"); 

     t1.start(); 

     try { 
      Thread.sleep(4000); 
     } 
     catch (InterruptedException e) {} 

     t2.start(); 
    } 
} 

class JoyRider implements Runnable { 

    private static boolean joy = false; 
    private boolean flag; 

    public JoyRider(boolean flag) { 
     this.flag = flag; 
    } 

    @Override 
    public void run() { 
     synchronized(this) { 
      if (flag) { 
       notifyJoy(); 
      } 
      else { 
       while (!joy) { 
        System.out.println("No Joy Yet..."); 
        try { 
         this.wait(); 
        } 
        catch (InterruptedException e) {} 
       } 
       System.out.println("Joy has been achieved!"); 
      } 
     } 
    } 

    public synchronized void notifyJoy() { 
     System.out.println("Notifying Joy"); 
     joy = true; 
     notifyAll(); 
    } 
} 

回答

3

要调用在不同的显示器wait()notifyAll(),更具体地说,在两个不同的JoyRider实例的内置显示器。

如果引入了一个专用的锁对象:

private static final Object LOCK = new Object();

,改变你的run()方法一点:

synchronized (LOCK) { 
    if (flag) { 
     System.out.println("Notifying Joy"); 
     JOY = true; 
     LOCK.notifyAll(); 
    } 
    else { 
     while (!JOY) { 
     System.out.println("No Joy Yet..."); 
     try { 
      LOCK.wait(); 
     } 
     catch (InterruptedException e) {} 
     } 
     System.out.println("Joy has been achieved!"); 
    } 
} 

,你应该能够看到正确的顺序所有预期打印。

3

the docs开始为notifyAll

唤醒所有正在等待的线程此对象的监视器。

强调我的。您有两个JoyRider s,j1j2。他们每个人都自己拨打wait。因此,当您拨打notifyAll时,您只是通知等待该实例的线程(即j1只通知等待j1的线程,而j2仅通知等待j2的线程)。

您可以通过同步和锁定静态对象来解决此问题。因此,请添加private static final Object LOCK = new Object();,将您的方法更改为synchronize(LOCK),并拨打notifyAll和而不是this