2016-09-29 43 views
0

我寫了一個House類,它有四個同步方法。 我寫了四個線程,並希望他們一個接一個地運行。但只是第一次和第二次跑,另一次沒有?如何使用wait()和notifyAll()逐個運行線程?

public class House { 

    private boolean hasFoundation = false; 
    private boolean hasFrame = false; 
    private boolean hasWall = false; 
    private boolean hasRoof = false; 

    public synchronized void buildFoundation() { 
     hasFoundation = true; 
     System.out.println("foundation Ok"); 
     notifyAll(); 
    } 

    public synchronized void buildFrame() throws InterruptedException { 
     if (!hasFoundation) { 
      wait(); 
     } else { 
      hasFrame = true; 
      System.out.println("frame ok"); 
      notifyAll(); 
     } 
    } 

    public synchronized void buildWall() throws InterruptedException { 
     if (!hasFrame) { 
      wait(); 
     } else { 
      hasWall = true; 
      System.out.println("wall ok"); 
      notifyAll(); 
     } 
    } 

    public synchronized void buildRoof() throws InterruptedException { 
     if (!hasWall) { 
      wait(); 
     } else { 
      hasRoof = true; 
      System.out.println("roof ok"); 
      notifyAll(); 
     } 
    } 
} 

public class BuildAHouse { 

    public static void main(String[] args) { 
     House house = new House(); 

     ExecutorService exec = Executors.newCachedThreadPool(); 

     exec.execute(new FoundationTeam(house)); 
     exec.execute(new WallTeam(house)); 
     exec.execute(new RoofTeam(house)); 

     exec.execute(new FrameTeam(house)); 

     exec.shutdown(); 
    } 
} 

運行時,在main(),結果只是: 基礎確定 框架確定

其他兩個線程運行沒有帶!爲什麼?

的... Team類是這樣的:

public class FoundationTeam implements Runnable { 

    private House house; 

    public FoundationTeam(House house) { 
     this.house = house; 
    } 

    @Override 
    public void run() { 
     house.buildFoundation(); 
    } 

} 

這只是一個演示,我想知道如何使用wait()和notifyAll的()。

請解決這個問題好嗎?它只是我想要的一部分。 請告訴我爲什麼它不起作用,以及如何解決?

當調用wait()時,這個對象會不會被釋放?和其他線程不能調用其他同步方法?

+0

我不知道你在那些'... Team'類中,但你可能只執行一次該方法。線程被暫停,當他們得到通知時,他們繼續退出該方法,因爲他們從來沒有機會進入這個else子句,除了'FrameTeam' – kevto

+0

我不認爲你真的需要'wait()'和'notifyAll()':這裏已經有'ExecutorService',這是更高層次的同步抽象。請參閱http://stackoverflow.com/q/2153663/5521491 –

+0

我不認爲這是正確的用例。無論你想要實現這一點,都可以輕鬆實現。 例如等待通知: 1.生產者消費者 2.偶奇打印機使用2線程 3.使用3個線程以順序方式打印數字 – cody123

回答

2

如果你的方法並等待(),它是不會運行在else

注意什麼:)等(可不合邏輯喚醒,建議while循環。

+0

方法調用wait(),其他調用notifyAll()不能喚醒? – Oolong

+0

@Oolong如果你等待()你沒有做其他事情。 –

0

這是工作!

public synchronized void buildWall() throws InterruptedException { 
    while (!hasFrame) { 
     wait(); 
    } 
    hasWall = true; 
    System.out.println("wall ok"); 
    notifyAll(); 
} 

添加「while()」,但我不知道爲什麼!

+0

因爲你需要等待,直到'hasFrame'成立。 'wait'函數不知道它正在等待什麼,也無法分辨它是否等待發生。所以這是你的責任。 –

1

另外兩個線程不能運行!爲什麼?

正如@Peter提到的那樣,你已經想通了,你需要在等待循環周圍循環使用while(!boolean)。這有幾個原因是必要的。

正如Peter提到的那樣,wait()可能會因虛假喚醒而不是正確調用notify()而返回。您需要確保您正在等待的條件已經設置好,然後循環並再次撥打wait()(如果沒有)。

然而,就你而言,關於虛假喚醒和更多關於如何編寫程序的內容不多。因爲您有一個​​對象(House對象),所以當您調用notifyAll()時,所有隊線程都被喚醒。當調用buildFoundation()方法時,它將hasFoundation設置爲true並喚醒所有團隊。但是隻有框架團隊才能真正開始工作 - 其他團隊需要循環並等待更多,直到他們的布爾值被設置爲true。

您可以更改您的代碼以使用不同的鎖定每個步驟使代碼更容易遵循,雖然您仍然需要while循環。

最後,正如你已經知道的那樣,你的if ... else ...模式沒有意義,因爲當團隊等待時,當他們被通知時,他們的構建方法將會返回,因爲其他東西在else

相關問題