2013-10-22 133 views
1

所以我一直在研究一個簡單的等待/通知的例子在Java中,由於某些原因,我一直無法讓它正常運行。如果有人能夠看到可能是什麼問題,將非常感謝!Java等待/通知不起作用

public class ThreadDemonstration 
{ 
private String str = null; 

Thread stringCreator = new Thread(new Runnable() 
{ 
    public void run() 
    {   
     synchronized(this) 
     {    
      str = "I have text"; 
      notify();    
     } 
    } 
}); 

private Thread stringUser = new Thread(new Runnable() 
{ 
    public void run() 
    { 
     synchronized(this) 
     { 
      if(str == null) 
      {     
       try { 
        System.out.println("str is null, I need help from stringCreator"); 
        wait(); 
        System.out.println(str); 
       } 
       catch (InterruptedException e) 
       { 
        e.printStackTrace(); 
       } 
      } 

     } 
    } 
}); 

public static void main (String [] args) 
{ 
    ThreadDemonstration td = new ThreadDemonstration(); 
    td.stringUser.start(); 
    td.stringCreator.start(); 
} 

}

我的電流輸出爲: str是空的,我需要從stringCreator

幫助,所以出於某種原因線程stringCreator沒有醒stringUser還是我失去了完全是另一回事?

謝謝!

+1

您認爲'new'的Runnable(){...}'值是多少? – Pshemo

+0

我現在明白了,謝謝:) –

回答

4

您的區塊爲​​,覆蓋不同的物件。他們應該是​​過公共對象,例如下面的monitor對象:

public class ThreadDemonstration 
{ 
private String str = null; 
    private final Object monitor = new Object(); 

Thread stringCreator = new Thread(new Runnable() 
{ 
    public void run() 
    {   
     synchronized(monitor) 
     {    
      str = "I have text"; 
      monitor.notify();    
     } 
    } 
}); 

private Thread stringUser = new Thread(new Runnable() 
{ 
    public void run() 
    { 
     synchronized(monitor) 
     { 
      while(str == null) //changed from if to while. This allows you to wait again if the thread gets woken up by something other than the appropriate notify. 
      {     
       try { 
        System.out.println("str is null, I need help from stringCreator"); 
        monitor.wait(); 
        //removed print statement from here 
       } 
       catch (InterruptedException e) 
       { 
        e.printStackTrace(); 
       } 
      } 
      System.out.println(str); //added print statement here. str is guaranteed to not be null here. 
     } 
    } 
}); 

爲了避免創建同步單獨的對象,可以使用例如synchronized(ThreadDemonstration.this)synchronized(ThreadDemonstration.class)

+0

謝謝,我已經更新了相應的例子。 – Piovezan

+0

大獲成功!謝謝你Piovezan! :-) –

+0

仍不確定這是否完整。如果'StringCreator'首先獲得鎖,它將設置'str',然後'notify()'。當'StringUser'獲得鎖時'str'不爲null,所以它不會'wait()'(這很好),但它也不會打印'str'。 – Cruncher

1

試試這個:

private Thread stringUser = new Thread(new Runnable() { 
    //----- 

    System.out.println("str is null, I need help from stringCreator"); 
    notify(); 
    wait(100); 
    System.out.println(str); 

    //---- 
}); 
+0

記得將代碼添加到代碼塊以獲得更好的格式化 –

+0

在此代碼中還有1個大括號和3個大括號。 – Cruncher

0

您需要使用相同的實例的waitnotify以便爲它工作。由於您創建了兩個不同的對象(Runnable的兩個實例),它將無法工作。我已經寫了一個簡單的例子,它使用兩個不同的類,使用主類的內部鎖的實例。你也可以爲我們設置一個「虛擬對象」(Object lock = new Object)。

public class ThreadDemonstration { 

    private static String text; 

    public ThreadDemonstration(){ 
     Thread user = new Thread(new StringUser(this)); 
     Thread creator = new Thread(new StringCreator(this)); 
     user.start(); 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     creator.start(); 
    } 

    public class StringCreator implements Runnable{ 

     private Object lock; 

     StringCreator(Object lock){ 
      this.lock = lock; 
     } 

     @Override 
     public void run() { 
      synchronized(lock){ 
       text = "Yeeeehaaaaa"; 
       lock.notify(); 
      } 

     } 

    } 

    public class StringUser implements Runnable{ 

     private Object lock; 

     StringUser(Object lock){ 
      this.lock = lock; 
     } 

     @Override 
     public void run() { 

      synchronized(lock){ 

       if((text == null)){ 
        System.out.println("I need help!"); 
        try { 
         lock.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
       System.out.println(text); 
      } 

     } 

    } 

    public static void main(String[] args){ 
     new ThreadDemonstration(); 
    } 

}