2012-08-14 150 views
2

我打算寫一個生產者和消費者線程之間的共享緩衝區。這裏是我的代碼:如何在Java線程之間實現共享緩衝區?

class PQueue 
{ 
    Token token; 
    boolean flag = false; // false: add, true: poll 

    PQueue() 
    { 
     token = null; 
    } 

    synchronized void add(Token token) 
    { 
     if(flag == true) 
     { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     flag = true; 
     notify(); 
     this.token = token; 
    } 

    synchronized Token poll() 
    { 
     if(flag == false) 
     { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     flag = false; 
     notify(); 
     return this.token; 
    } 
} 

我是多線程新手。是否有任何潛在的併發錯誤?這是實現這一目標的「標準/普通」方式嗎?還是有更簡單更有效的方法?

+1

難道你不能只使用java.util.concurrent.BlockingQueue? – vanza 2012-08-14 05:24:53

+0

'notify()'在同步塊內部看起來對我來說很可疑(但不能確定它是否有效或導致死鎖) – 2012-08-14 05:26:25

+1

@Andreas_D:你不能以任何其他方式調用notify(),你是什麼意思可疑? (他的代碼由於其他原因是可疑的,但不是那個。) – vanza 2012-08-14 05:28:24

回答

3

查看java.util.concurrent程序包,特別是BlockingQueue接口以及實現它的類。這些是爲了將消息從一個線程傳遞到另一個線程。 SynchronousQueue正是你想要實現的。

你自己的實現有一些缺陷。首先,兩個共享變量應該聲明爲volatile以確保一個線程上的更改可以被另一個線程看到。而您的if (flag == false)if (flag == true)測試實際上應該是while循環,因爲wait()可以wake up spuriouslynotify()尚未實際調用。

而不是有一個單獨的標誌變量,我建議只是將標記設置爲空以表明沒有對象。而不是抓住,打印,並在InterruptedException面前盲目繼續,我建議讓這兩種方法只是拋出異常,如果它發生。這些是阻塞方法,並且調用者有責任處理阻塞方法被中斷的可能性。

此外,我不知道你的Token類是什麼,但你的隊列中沒有任何東西實際上取決於它的類型。定義通用的PQueue<T>會更有意義,如果要傳遞令牌,則使用PQueue<Token>

1

1.嘗試使用thread-safe類和java.util.concurrent包的接口。

2.使用BlockingQueueInterfaceArrayBlockingQueueClass一起。