5

データベースからハードディスクへのファイルキャッシュを同期しようとしています。

ファイルが存在するかどうかを確認し、そうでない場合はデータベースからファイルを取得して展開します。競合状態のため、ファイルを複数回書き込みたくありません。

ここに私が作ったコードがあります:

重要: このコードは、そのすべての意味を持つ 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 回書き込むことはありません。

助言がありますか?

ありがとう。

4

2 に答える 2

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); 
于 2013-07-09T23:44:09.723 に答える