2014-05-14 20 views
1

我有這樣一個類:Java併發:一些援助

package crossRoadConcurency; 

import java.util.List; 

public class TourGuide 
{ 
    private volatile boolean isGuiding; 
    private volatile boolean isInShop; 
    private final Object lockObject = new Object(); 
    private final int id; 

    public TourGuide(int id) 
    { 
     this.isGuiding=false; 
     this.isInShop=false; 
     this.id=id; 
    } 

    public synchronized boolean isFree() 
    { 
     return !isGuiding && !isInShop; 
    } 

    public void guide(final Tourist[] tourists) 
{ 
    new Thread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      synchronized (lockObject) 
      { 
       while(!isFree()) 
       { 
        try 
        { 
         System.out.println("Guide "+id+" is bussy. Waiting... "); 
         lockObject.wait(); 
        } 
        catch (InterruptedException e) 
        { 
         e.printStackTrace(); 
        } 
       } 
      } 
      isGuiding=true; 
      System.out.println("Guide "+id+" is guiding "+tourists.length+" tourists"); 
      try 
      { 
       Thread.sleep(4000);//lets not wait one hour, shall we? 
       for (Tourist tourist : tourists) 
       { 
        tourist.exit(); 
       } 
       System.out.println("All tourists exited for guide "+id+". Going to shop"); 
       isInShop=true; 
       isGuiding=false;//if we invert the way we give these values bad thing may happen 
       Thread.sleep(4000); 
       isInShop=false; 
       System.out.println("Guide "+id+" is free"); 
       synchronized (lockObject) 
       { 
        lockObject.notifyAll(); 
       } 
      } 
      catch (InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 

     } 
    }).start(); 
} 
} 

而另一個類:

package crossRoadConcurency; 

import java.util.Random; 

public class Tourist 
{ 
    public void exit() throws InterruptedException 
    { 
     Random random = new Random(); 
     Thread.sleep(random.nextInt(1000));// max one second to exit 
    } 
} 

,我用這樣的:

package crossRoadConcurency; 

import java.util.List; 

public class Main 
{ 

    public static void main(String[] args) throws InterruptedException 
    { 
     Tourist[] tourists = new Tourist[20]; 
     for (int i=0;i<tourists.length;i++) 
     { 
      tourists[i]=new Tourist(); 
     } 
     TourGuide guide = new TourGuide(0); 
     guide.guide(tourists); 
      Thread.sleep(500); 
     guide.guide(tourists); 

    } 

} 

的問題是我得到這個輸出:

Guide 0 is guiding 20 tourists 
All tourists exited for guide 0. Going to shop 
Guide 0 is free 
Exception in thread "Thread-0" Guide 0 is guiding 20 tourists 
java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at crossRoadConcurency.TourGide$1.run(TourGide.java:60) 
    at java.lang.Thread.run(Unknown Source) 
All tourists exited for guide 0. Going to shop 
Guide 0 is free 
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at crossRoadConcurency.TourGide$1.run(TourGide.java:60) 
    at java.lang.Thread.run(Unknown Source) 

第一個問題:爲什麼我沒有看到「等待輸出」
第二個問題:爲什麼我會得到一個異常
第三個問題:有沒有更好的方式來做到這一點,因爲我相當肯定這個概念是混淆

回答

1
  1. 你沒有看到「等待」,因爲你的嚮導是默認免費。 !isGuide && !isInShop返回true,而您僅在!isFree()時打印。

  2. 您應該致電lockObject.notifyAll()。直接調用notifyAll()默認情況下調用此對象,並且您肯定沒有執行實現Runnable接口的Anoymous對象的監視器,因爲您從來沒有通過調用synchroized(this)執行此操作。這就是你得到這個例外的原因。

  3. 是的。您應該使用Executor,例如SingleThreadExecutor以及一個併發隊列。除非您繼續進行高性能計算,否則這是實現併發性的強大且簡單的方法。該軟件包還提供了出色的功能和支持功能類。檢查出java.util.concurrent

順便說一句,您的軟件包名稱包含不受java編程規範推薦的大寫字母。

+0

1.默認情況下他,但看到主要的方法 - 我有2個電話指導方法,其中第二個應該趕上繁忙模式的指導。 2.請參閱編輯的問題。我仍然得到異常 –

+0

你啓動了2個線程,但是你可以在任何線程將它們設置爲true之前先讓這兩個線程檢查這個標誌。 –

+0

@ user3580294但是這並沒有用,因爲他在方法內部啓動另一個線程並運行它。在那個線程裏面,他依賴於lockObject。您在該方法上同步只會導致線程的創建和啓動被同步。 –

-1

當我們同步任何塊或方法時,我們應該對類鎖或對象鎖進行同步。

但在這裏,你已經鎖定某些對象,它是沒有地方有關該方法的調用者

所以改變這種從下面synchronized (lockObject)喜歡和運行

synchronized (this) 
+0

如果你在'lockObject'看到OP的調用'wait()'和'notifyAll()',所以我認爲'synchronized'塊是正確的 – awksp

+0

ha我把輸出像下面那樣放在同步後(this)指南0是bussy 。等待... 指南0指導20名遊客 所有的遊客都爲參考0而退出。去商店 指南0是免費的 –

+0

...我實際上沒有得到OP的代碼例外......所以也許不是那個部分這是扔掉的東西。 – awksp