2016-01-03 50 views
1

我想模擬一個母親通話三個子吃晚飯,這裏是我的代碼:的Java notifyAll的:拋出:IllegalMonitorStateException

class child extends Thread{ 
    String name; 
    mother mom; 
    public child(mother mon, String name){ 
     this.name = name; 
     this.mom = mom; 
    } 

    public void run(){ 
     System.out.println(name+" is hungry."); 
     while (!mom.finished){ 
      try { 
       wait(); 
      }catch(InterruptedException e){} 
     } 
     washhands(); 
    } 

    public synchronized void washhands(){ 
     System.out.println(name+" washed hands."); 
     notifyAll(); 
    } 
} 

class mother{ 
    boolean finished; 

    public mother(){ 
     finished = false; 
    } 
    public void cook(){ 
     System.out.println("Mom started cooking."); 
     try{ 
      Thread.sleep(200); 
     }catch(InterruptedException e){}; 
     finished = true; 
     System.out.println("Mom finished cooking."); 
     notifyAll(); 
    } 
} 

public class work{ 
    public static void main(String[] args){ 
     mother mom = new mother(); 
     child Alex = new child(mom, "Alex"); 
     child James = new child(mom, "James"); 
     child Tod = new child(mom, "Tod"); 

     Alex.start(); 
     James.start(); 
     Tod.start(); 
     mom.cook(); 
    } 
} 

所以我「在線程異常‘主’java.lang.IllegalMonitorStateException」得到了在類的母親notifyAll()的行。我不知道會發生什麼,有人能幫助我嗎?

+0

wait和notify只能在有人看守的塊被調用,看看這個鏈接https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth .html – 11thdimension

+0

您是否需要直接使用wait和notifyAll?如果不是,我建議'java.util.concurrent.Semaphore「。 –

+0

你需要在Mom類中捕獲子對象,然後通知他們 –

回答

0

考慮以下幾點。

  1. 你必須使用一個通用對象來保護所有需要互斥的代碼塊。
  2. 如果監視器被當前線程鎖定,則只能在對象上調用wait/notify。
  3. 要獲取監視器,線程必須輸入一個由擁有監視器的對象保護的塊。監視器由JVM在內部使用。使用Java naming conventions.

    見下

    synchronized void method1() { 
    } 
    
    synchronized void method2() { 
    } 
    

    這裏method1method2代碼將通過對象的顯示器上這些將被稱爲看守

除了它命名類和變量。因此,如果我們想在防護塊內使用相同的顯示器,它將按照以下方式完成。

public void method3() { 
    synchronized(this) { 
    } 
    ... 
} 

現在method1()method2()和守衛塊method3()將通過同一個對象監控保護。

如果我們需要跨類的保護塊,那麼我們需要在它們之間共享一個共同的對象。我在下面的代碼中做了相同的修改。

package filevisitor; 

import java.util.Random; 
import java.util.concurrent.atomic.AtomicLong; 

class child extends Thread{ 
    String name; 
    volatile mother mom; 
    public child(mother mom, String name){ 
     this.name = name; 
     this.mom = mom; 
    } 

    public void run(){ 
     System.out.println(name+" is hungry."); 
     while (!mom.finished){ 
      try { 
       synchronized(work.myLockObject) { 
        work.myLockObject.wait(); 
       } 
      }catch(InterruptedException e){} 
     } 
     washhands(); 
    } 

    public void washhands(){ 
     System.out.println(name+" washed hands."); 
     synchronized(work.myLockObject) { 
      work.myLockObject.notifyAll(); 
     } 
    } 
} 

class mother{ 
    boolean finished; 

    public mother(){ 
     finished = false; 
    } 
    public void cook(){ 
     System.out.println("Mom started cooking."); 
     try{ 
      Thread.sleep(200); 
     }catch(InterruptedException e){}; 
     finished = true; 
     System.out.println("Mom finished cooking."); 
     synchronized(work.myLockObject) { 
      work.myLockObject.notifyAll(); 
     } 
    } 
} 

public class work{ 
    public static final Object myLockObject = new Object(); 
    public static void main(String[] args){ 
     mother mom = new mother(); 
     child Alex = new child(mom, "Alex"); 
     child James = new child(mom, "James"); 
     child Tod = new child(mom, "Tod"); 

     Alex.start(); 
     James.start(); 
     Tod.start(); 
     mom.cook(); 
    } 
} 

此外,在兒童班this.mom = mom;還有一個小錯誤。參數名稱是mon,所以這項任務沒有做任何事,導致NullPointerException

輸出

Mom started cooking. 
Alex is hungry. 
Tod is hungry. 
James is hungry. 
Mom finished cooking. 
Tod washed hands. 
James washed hands. 
Alex washed hands. 
0

因爲一旦媽媽烹飪完畢,您需要通知孩子。現在你正在對媽媽對象本身調用notifyAll(),這在功能上看起來不正確。一種方法是將兒童對象參考傳遞給媽媽,並在媽媽完成烹飪後通知他們

相關問題