2010-06-17 53 views
2

我試圖建立一個半文件共享程序,當每臺計算機都扮演服務器和客戶端的角色時。在java中刪除文件,同時將其上傳到其他線程

我給多個線程選項從我的系統DL文件。

另外,我有一個用戶界面,可以接收刪除消息。

我的問題是,我希望一分鐘刪除消息receiedved,我等待DL文件完成DL的所有線程,只有比excute file.delete()。 做什麼是最好的方法?

我想過一些數據庫保存>並迭代並檢查線程是否活動,但它似乎笨拙。有沒有更好的辦法? 謝謝

+0

正如我記得喬爾在最初的土豚規範中所採取的方法。 – Woot4Moo 2010-06-17 17:28:20

回答

0

如果您必須等待所有讀取器完成,您的刪除事件處理線程(可能是您的UI)將變爲無響應。相反,排隊刪除並定期輪詢可以處理的刪除。您可以使用:

private class DeleteRunnable implements Runnable { 
public void run() { 
    while (!done) { 
    ArrayList<DeletedObject> tmpList = null; 
    synchronized (masterList) { 
    tmpList = new ArrayList<DeletedObjects>(masterList); 
    } 

    for (DeletedObject o : tmpList) 
    if (o.waitForReaders(500, TimeUnit.MilliSeconds)) 
    synchronized (masterList) { 
     masterList.remove(o); 
    } 
    } 
} 
} 
2

我認爲你可以做到這一點比使用數據庫更簡單。我將圍繞File ..一個TrackedFile放置一個薄包裝類。它裏面有文件,並有多少人正在閱讀它。當你刪除時,只需停止允許新用戶抓取文件,並等待計數達到0.

由於您正在處理訪問共享狀態的許多線程,因此請確保正確使用java.util。同時

1

我不知道這解決所有的問題,但是這是我的想法:只有從同一個應用程序中發生的操作

Assumming所有的讀/寫/刪除,線程同步機制使用鎖可以是有用的。

對於每個到達的新文件,都可以創建新的讀/寫鎖(請參閱Java的ReentrantReadWriteLock)。應該爲所有讀取操作獲取讀取鎖定,而應該爲寫入/刪除操作獲取寫入鎖定。當然,當獲得鎖定時,您應該檢查操作是否仍然有意義(即文件是否仍然存在)。

+0

我喜歡它。當一個進程管理文件時,'ReentrantReadWriteLock'比嘗試使用另一個工具如數據庫或文件系統鎖進行同步要簡單得多。 – erickson 2010-06-17 17:43:40

0

如果你要調整你的設計只是稍微讓加載從磁盤上的文件和將文件上傳到客戶端並沒有在同一個線程中完成的,你可以等待文件停止只需通過從讀取該文件中鎖定新線程來訪問,然後遍歷從該文件讀取的所有線程,並對每個線程執行join(),一次一個。只要文件讀取線程在加載文件後立即終止,迭代就會在最後一個線程不再讀取文件的那一刻完成,並且您很好。

以下段落的基礎是假設您重複讀取文件數據多次,即使讀取線程都在相同的一般時間範圍內讀取,因爲這聽起來就像您正在做的。

這樣做,將文件閱讀分離爲單獨的線程,也可以讓您有一個線程加載特定文件,並讓多個客戶端上傳從單個閱讀過程中的數據獲取文件中的數據。有幾種優化可以用這個來實現,這取決於這是什麼類型的項目。如果你這樣做,確保你不會在內存中保存太多的文件數據,否則很明顯會發生。但是,如果您的項目性質保證有少量和/或小文件不會佔用太多內存,這是將文件加載分離爲單獨的線程的一個很好的副作用。

如果你走這條使用join()的路線,你可以使用join(毫秒)變體,如果你想讓刪除線程能夠等待一段時間然後要求其他線程停止(對於大文件和/或許多文件被訪問的時間,因此HD正在變慢),如果它們還沒有。只需獲取(now + theDurationYouWantToWait)和加入(impatientTimestamp-currentTimestamp)的時間戳,並在if(currentTimestamp> = impatientTimestamp)循環的中間向所有文件加載線程發送一箇中斷 - 然後將文件加載線程在他們正在讀取文件數據的循環中檢查它,然後重新加入()連接(毫秒)中止的線程並繼續您正在執行的join()迭代。

相關問題