2015-05-31 59 views
0

我想測試以查看是否可以鎖定文件X.如果文件不存在或無法鎖定,則失敗。這聽起來很簡單,但我一直陷入死衚衕。答案的一個捷徑是提供一種方法來獲得一個FileChannel,我可以獨佔鎖,而沒有任何創建文件的風險。讓我解釋一下......如何鎖定文件,如果存在,請不要創建它?

我不能使用NIO lock()而沒有可寫的FileChannel,而且我不能在不打開文件X的情況下獲得可寫的FileChannel,如果它不存在,就會創建它。我找到的每個Java方法都試圖打開文件X爲可寫,如果它不存在,並且似乎沒有辦法在只讀文件通道上專門鎖定文件,就會創建它。

即使首先檢查確認文件是否存在也是有問題的。這裏是我的最新代碼:

private LockStatus openAndLockFile(File file) { 

      if (Files.notExists(file.toPath())) { 
       synchronized (fileList) { 
        removeFile(file); 
       } 
       return LockStatus.FILE_NOT_FOUND; 
      } 
      try { 
       rwFile = new RandomAccessFile(file, "rw"); 
       fileLock = rwFile.getChannel().lock();     
      } 
      catch ... 

這段代碼的問題是NotExists代碼運行時該文件可能存在,但由new RandomAccessFile(file, "rw")運行的時間消失。這是因爲我在多個線程和多個進程中運行此代碼,這意味着代碼必須密封並且堅如磐石。

下面是在兩個過程運行與我的現有代碼的問題的一個例子:

1:方法A檢測到新文件

2:方法B檢測到相同的文件

3:處理A處理文件並將其移動到另一個文件夾

問題--->處理B意外地創建一個空文件。 OOPS!

4:進程B檢測到進程B創建的新文件,並處理它創建一個0字節的重複文件。

5:進程A也檢測不小心被進程B創建新的文件,並試圖對其進行處理......

Bigger screenshot

http://i.imgur.com/kLMnXlz.png

下面是使用的什麼我C#示例試圖做到:

Stream iStream = File.Open("c:\\software\\code.txt", FileMode.Open, 
    FileAccess.Read, FileShare.None) 

任何幫助或提示,非常感謝!謝謝!

+0

圍繞關鍵塊同步 – MadProgrammer

+0

感謝您的建議。當代碼在完全獨立的進程中運行時,這是如何工作的?可能在不同的機器上? –

+0

那麼顯然使用文件是錯誤的方法,除非文件系統在這些機器之間共享。這可能會更好:http://stackoverflow.com/questions/1059580/distributed-lock-service –

回答

1

如果您試圖阻止同一應用程序(同一個JVM)中的兩個線程處理同一個文件,那麼您應該使用常規Java鎖實現此操作,而不是使用文件鎖。文件鎖被授予JVM並且是可重入的......所以如果一個線程「鎖定」一個文件,另一個線程就可以獲得對同一個文件的鎖定。

我會做的是創建一個線程安全鎖定類,它包裝了一個HashSet<File>,其中File對象表示存在的文件的絕對文件路徑。然後通過鎖定File對象來實現「文件鎖定」。


不幸的是他們不僅將在不同的JVM,它們可能會有所不同的服務器上。

在這種情況下,最好的策略可能是使用數據庫來實現鎖定。

+0

好點。不幸的是,他們不僅會處於不同的JVM中,他們有時會處於不同的服務器上。 –

相關問題