尝试在java中同步文件写入系统

Gle*_*eeb 5 java concurrency

我正在尝试从数据库同步硬盘上的文件兑现.

我正在检查文件是否存在,如果不存在,我从数据库中获取文件并进行部署.由于Race条件,我不想多次写文件.

这是我制作的代码:

重要提示:此代码位于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;
}
Run Code Online (Sandbox Code Playgroud)

有了这个解决方案,我找不到文件,我真的不会写文件2次以及任何其他文件,因为我正在同步整个块,所有线程试图到达它,即使是要写一个不同的文件.

有什么建议?

谢谢.

Pet*_*rey 5

与@ Avi的解决方案类似,但使用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); 
Run Code Online (Sandbox Code Playgroud)


Avi*_*Avi 2

创建一个 of 锁怎么样HashMap?键将是文件路径,值将只是用作锁的对象。假设这张地图的定义如下:

Map<String, Object> locks = new Map<String, Object>();
Run Code Online (Sandbox Code Playgroud)

这就是用途:

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)); 
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `map.remove(lock);` 并没有按照你的想法做,在这种情况下,什么也不做。我认为你的意思是“map.remove(file.getName());” (2认同)