2009-12-26 128 views
1

我正在編寫類似於生產者 - 消費者問題的程序。這是我的主代碼:終止前清理緩衝區

public class PipeProcessor { 

private volatile boolean close = false; 

Pipe pipe; 
Output out; 

public PipeProcessor(Pipe pipe) 
{ 
    this.pipe = pipe; 
} 

public void run() 
{ 
    while(!close) 
    { 
     out.output(pipe.get()); 
    } 

    while(pipe.size() > 0) 
     out.output(pipe.get()); 

    out.close(); 

} 

public void close() 
{ 
    close = true; 
} 
} 

管道是ArrayBlockingQueue的包裝並充當緩衝區。輸出是一個將緩衝區中的元素輸出的類。

我想確保PipeProcessor乾淨地終止,即當它被髮信號關閉時,它會清除緩衝區。由於關閉鉤子調用close()方法,所以我確定處理器關閉時緩衝區沒有被填充, 這是正確的方法嗎?謝謝。

回答

0

不確定爲什麼您在關閉時試圖清理管道,爲什麼不丟棄它並讓GC清理它?只要我能看到,你所需要的就是關閉和第一個循環。

+0

因爲我想在關閉程序之前輸出緩衝區中的所有剩餘元素,而不是丟棄它們。 – 2009-12-26 10:10:05

1

它看起來像你的代碼做你想做的事情。如果你看一下你的命名,你可以讓你的代碼更容易理解,例如布爾「close」可以被命名爲「closing」或「shuttingDown」,或者將其反轉爲「running」,這將導致更易讀的代碼imho。

的同時run()循環和它後面的行可以寫成:

while (running || pipe.size() > 0) { 

     out.output(pipe.get()); 
    } 
+0

感謝您的提示:-) – 2009-12-26 10:51:15

0

如果要處理管道中的所有元素的過程中停止之前,我不認爲我會實際上使用關閉鉤子 - 我會在主代碼中明確關閉管道,然後在讓主線程完成之前等待它完成。我建議你將close()方法更改爲阻塞,直到流水線結束,或者添加一個單獨的方法(例如waitForPipelineToEmpty())。

通過這種方式,您可以使其更具可控性 - 特別是,這意味着您不會嘗試處理事情,而系統的其他位正在清理自己的關機掛鉤。

終止生產者/消費者隊列的另一種方法是擁有一個標記值,意思是「立即停止」。然後,您只需將其饋入管道的末端(並避免添加更多「真實」值),並且您的處理器在看到該項目時就停下來。

+0

你是對的。但在我的情況下,我正在構建一個分析器,該分析器應該在分析程序終止時關閉。配置文件程序在管道上生成,而另一個線程PipedProcessor將使用該配置文件。 – 2009-12-26 10:29:12

1

我擔心out.close()不一定會被調用。如果Pipe.get()像ArrayBlockingQueue.take()那樣阻塞,並且它在檢測到閉包時不返回標記值,那麼在Pipe爲空後在PipeProcessor上調用close()將不起作用,因爲while(!close)條件不會再次評估。 (1)Pipe會始終關閉,(2)Pipe.get()檢測到關閉,並且(3)它返回一些像Output一樣可以處理的null的sentinel值。如果是這種情況,那麼你的代碼看起來不錯。