2013-10-02 27 views
0

我絕對是在一個併發地獄。我無法找到我想要做的一個好的/有效的解決方案。我有一個生產者線程正在讀取文本文件並將信息放入共享的BlockedQueue中。我有一個消費者使用共享的BlockedQueue來讀取數據,並對數據做了很多事情。我有一個GUI有三個按鈕:開始,暫停停止如何開始,暫停和停止生產者/消費者關係?

生產者和消費者雙方實現Runnable,並提供方法來訪問有關每個人的計算信息(例如,返回一些統計或某些對象)

隨着開始選擇我想要的生產者打開一個文件並開始將數據放入BlockedQueue。消費者也開始採集數據並進行計算。

暫停選項我希望生產者停止將數據放入BlockedQueue,但同時我希望能夠訪問生產者的實例變量。消費者也是這樣,我想停止執行繁重的工作,但仍然能夠訪問消費者中定義的一些實例變量和方法。

隨着停止選項我希望生產者和消費者重置...即,就好像從乾淨開始。

我的問題是如何有效地實現這個?特別是要檢查暫停?

這樣的psudo-code會有效嗎?

Enum state; 

class Producer implements Runnable { 
    public List someList;//accessed from the event-dispatching thread 
    public void Run() { 
     synchronized(state) { 
      if(state == Enum.paused) { 
       //do nothing 
      } 
      else if(state == Enum.running) { 
       //put stuff into BlockedQueue 
      } 
      else if (state == Enum.stopped) { 
       // reopen file and set state = running 
      } 


     } 
    } 
} 

class Consumer implements Runnable { 
    public Map someMap;//accessed from the event-dispatching thread 
    public void Run() { 
     synchronized(state) { 
      if(state == Enum.paused) { 
       //do nothing 
      } 
      else if(state == Enum.running) { 
       //start consuming from the BlockedQueue and do heavy computation 
      } 
      else if (state == Enum.stopped) { 
       // clear stuff to start clean and set state = running 
      } 


     } 
    } 
} 
+0

旁註:保持你的枚舉一致。現在你有一個描述狀態('isPause'),描述當前行爲('running')和描述行爲('stop')的狀態。 –

+2

看看'毒丸'。 –

+0

在Brian Goetz等人的第7章中,這個問題聽起來像是一場營銷活動。實踐中的Java併發。本章討論可取消性和可中斷性,並解釋說:「......程序如何處理取消和關閉通常是將真正健壯的併發應用程序與僅僅工作的應用程序分開的因素之一。」它比Joshua Bloch的Effective Java,2nd Ed更高級一些,但對於那些希望在Java中進行嚴肅的併發編程的人來說這是一個必讀書(它涵蓋了毒藥丸)。 – scottb

回答

1

我的問題是如何有效地實現這個?特別是要檢查暫停?像這樣的psudo-code會有效嗎?

我認爲使用ConsumerProducer上的字段是一個很好的方法。您需要確保該字段爲volatile,以便任何對枚舉的更新都在線程之間正確同步。或者,如果您使用​​關鍵字,則更新時需要有​​。 volatile在這種情況下更好,因爲沒有理由阻止。

public class Consumer { 
    private volatile Enum state; 
    ... 
    if(state == Enum.paused) { 

人們提到了一種「毒丸」作爲解決方案。這是當你將一個對象放入改變狀態的隊列中。這個解決方案的問題是,如果消費者正在處理該對象,它將不會檢查隊列,因此這將不起作用。我想你可以在隊列peek()state領域應該正常工作。

生產者和消費者都實現了Runnable並提供訪問每個計算的信息的方法(例如,返回一些統計數據或某些對象)

ProducerConsumer對象仍然存在,並會訪問。在所有情況下,您都需要確保對線程之間共享的字段進行的任何更新都需要進行正確的同步。

我的問題是如何有效地實現這個?特別是要檢查暫停?

就效率而言,volatile字段訪問似乎比典型的字段訪問慢100倍。我不會在每一行都進行狀態檢查,但是如果您在每個處理循環的頂部檢查它,或者執行類似if (loopCounter % 1000 == 0)的操作來檢查循環中每隔X次的暫停情況,您應該不會看到任何性能下降。

+1

我想說的關鍵在於掌握InterruptedException成語。 – scottb

+0

@格雷你能在這裏檢查我的問題嗎? http://stackoverflow.com/questions/19177770/how-to-make-two-threads-wait-then-run-given-that-they-use-a-blockedqueue –

0

您可以標記進入隊列的消息,無論它們是數據還是控制消息。每個線程只有一個輸入(消息)隊列。