2013-07-09 47 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的解决方案好。 –