2017-06-22 109 views
2

我有一個程序,其中有幾個線程寫入緩衝區,並且有一個線程從緩衝區讀取並寫入文件。 緩衝區的實現方式是,當緩衝區爲空時導致線程阻塞(使用wait())時嘗試提取條目。 線程使用BufferedStream寫入文件。 目前我每次寫入文件10次後都會沖洗BufferedStream。Java喚醒阻塞線程定期

while (true) 
{ 
    BufferEntry entry = buffer.getEntry(); // might block 

    logFile.printf("%s", entry); 

    ++entriesWritten; 

    if (entriesWritten >= 10) 
    { 
     logFile.flush(); 
     entriesWritten = 0; 
    } 
} 

然而,我想覆蓋其中寫入X條目(X < 10)之後,緩衝器保持爲空了很長時間的使用情況。 我希望緩衝區中的條目長於一段時間才能寫入文件。

我正在考慮一個守護進程,它會定期喚醒來處理沖洗,但是這樣的守護進程將意味着多個線程將處理文件,這是不可取的。更不用說守護進程必須知道什麼時候寫入當前未刷新的條目...

我在考慮使用中斷方法並捕獲InterruptedException。但我擔心這種方法並不美觀,除此之外 - 寫入文件時收到的中斷可能導致需要處理的不同種類的異常。

我也有一個想法,重載緩衝區構造函數接收一個額外的參數,這將使緩衝區等待指定的分鐘數,而不是永遠。一旦醒來就可以檢查是否需要衝洗。我對這個解決方案的擔憂是給Buffer帶來了一些不應該擔心的事情,以及等待沒有返回任何指示的事實。

有沒有一種漂亮的方式來處理這種情況?

回答

0

你可能想看看Condition

這個類提供的對象監視器的方法(waitnotifynotifyAll)的功能 - 他們被稱爲awaitsignalsignalAll爲了避免名稱衝突與從Object繼承的方法。

什麼,你可能會感興趣的是方法awaitNanos,因爲它允許您指定超時:

造成當前線程在等待,直到它發出信號或中斷,或在指定的等待時間。

另一方面,也許簡單的Object.wait(long timeout)可能就足夠您的用例。

+0

我喜歡使用Lock和Condition的建議。 condition的方法await返回一個布爾值,表示線程是否由於超時而被喚醒。與Alexei的建議一樣,將getEntry重載以接收超時,這可能是解決問題的好辦法,同時仍然保持Buffer對象的一般性。謝謝! – Victoriia

0

你說buffer.getEntry()來電Object.wait()。實施另一種方法,buffer.getEntry(long timeout),它調用Object.wait(timeout),如果發生超時,則返回null。

 BufferEntry entry = buffer.getEntry(timeout); // might block 

    if (entry != null) { 
     logFile.printf("%s", entry); 
     ++entriesWritten; 
    } 

    if (entriesWritten >= 10 || entry == null) { 
     logFile.flush(); 
     entriesWritten = 0; 
    } 
+0

我喜歡你的想法重載getEntry方法。這樣Buffer就提供了一個附加服務,並且保持通用。在API文檔中,我沒有看到Object的等待方法顯示線程由於超時而被喚醒。我認爲綠巨人建議使用鎖定和條件,連同你建議重載方法將是一個很好的解決方案。謝謝 – Victoriia