2013-07-09 48 views
5

我想從數據庫中同步硬盤上的文件。試圖在java中同步文件寫入系統

我在做什麼檢查文件是否存在,如果不是我從數據庫中獲取文件並部署它。由於競爭條件,我不想多次寫入文件。

這裏是我做的代碼:

IMPORTENT:此代碼是一個Bean裏面有所有的含義

@Override 
public String getThumbnailPictureUrl(Design design) { 
    String relativePath = String.format(THUMBNAIL_URL, design.getId(), design.getThumbnailPicture().getFileName()); 
    String realPath = servletContext.getRealPath("/"+relativePath); 
    logger.info("Request Thumbnail picture for design: " + design.getId()); 
    logger.info("Thumbnail picture relative path: " + relativePath); 
    logger.info("Thumbnail picture real path: " + realPath);   
    File file = new File(realPath); 
    if(!file.exists()) 
    { 
     synchronized (thumbnailLock) 
     { 
      if(!file.exists()) 
      { 
      logger.warn("Could not fild file in path: " + realPath); 
      FileAttachment pictureAttachment = design.getThumbnailPicture(); 
      Hibernate.initialize(pictureAttachment.getAttachment()); 
      Data data = (Data) pictureAttachment.getAttachment(); 
      file = toolBox.convertBlobToFile(data.getBlob(), file); 
      logger.warn("file created in path: " + realPath); 
      } 
     } 
    } 
    return relativePath; 
} 

有了這個解決方案的情況下,我沒有找到該文件我真的不會寫文件2倍,以及任何其他文件,因爲我正在同步整個塊的所有線程試圖達到它,即使是寫一個不同的文件。

有什麼建議嗎?

謝謝。

+1

什麼版本的Java? – erickson

回答

1

如何創建鎖的HashMap?關鍵將是文件路徑,並且該值將只是一個用作鎖的對象。比方說,這張地圖是這樣定義的:

Map<String, Object> locks = new Map<String, Object>(); 

這是利用:

if(!file.exists()) 
{ 
    Object lock = null; 
    synchronized (locks) { 
     lock = locks.get(file.getName()); 
     if(lock == null) { 
      lock = new Object(); 
      locks.put(file.getName(), lock); 

     } 
    } 
    synchronized (lock) 
    { 
     if(!file.exists()) 
     { 
     logger.warn("Could not fild file in path: " + realPath); 
     FileAttachment pictureAttachment = design.getThumbnailPicture(); 
     Hibernate.initialize(pictureAttachment.getAttachment()); 
     Data data = (Data) pictureAttachment.getAttachment(); 
     file = toolBox.convertBlobToFile(data.getBlob(), file); 
     logger.warn("file created in path: " + realPath); 
     } 
    } 
    synchronized(locks) { 
     map.remove(lock)); 
    } 
} 
+0

文件路徑是動態的。我無法立即創建一個關鍵/對象並鎖定它......它具有相同的競爭條件。當我鎖定對象時,下面的線程已經將其替換爲新的線程 – Gleeb

+0

看看我的代碼,我認爲它解決了所有的競爭條件。至少我能想到的那些。 – Avi

+0

還有一些等待所有的文件。但原始關鍵部分已鎖定每個文件。 '鎖'表操作並不是非常昂貴(在時間處理中) – Avi

5

類似@阿維的解決方案,但使用的ConcurrentHashMap。

private final ConcurrentMap<String, Object> map = new ConcurrentHashMap<>(); 

String name = file.getName(); 
Object lock = map.get(name); 
if (lock == null) { 
    map.putIfAbsent(name, new Object()); 
    lock = map.get(name); 
} 

synchronized (lock) { 
    // do something 
} 

map.remove(name); 
+0

每次查詢文件存在時,您的解決方案都會創建新對象,因此並不總比@Avi的解決方案好。 –