2013-07-09 16 views
5

ハードディスクから現金化したファイルをデータベースから同期しようとしています。Javaでファイル書き込みシステムを同期しようとしています

ファイルが存在するかどうかを確認する際に何をしているのか、そうでない場合はファイルをデータベースから取り出して展開します。私はレースの条件のためにファイルを何度も書きたくないです。

にとって必須:ここ

は私が作ったコードです。このコードは、そのすべての意味を私は見つけていない場合は、このソリューションで

@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>(); 

そして、これが使用される:

アビのソリューション@しかし、ConcurrentHashMapのを使用するのと同様
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

まだすべてのファイルを待っています。しかし、元のクリティカルセクションはファイルごとにロックされます。 'locks'テーブルの操作は非常に高価ではありません(時間処理で) – Avi

5

のは、このマップは、次のように定義されているとしましょう。

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のソリューションよりも必ずしも良いとは限りません。 –

関連する問題