2013-07-09 27 views
5

Tôi đang cố gắng đồng bộ hóa một tệp tiền mặt trên đĩa cứng từ cơ sở dữ liệu.Cố gắng đồng bộ hóa một hệ thống ghi tệp bằng java

Tôi đang làm gì khi kiểm tra xem tệp có tồn tại không và nếu tôi không tìm nạp tệp từ cơ sở dữ liệu và triển khai tệp đó. Tôi không muốn viết tệp nhiều lần do điều kiện Race.

Đây là mã tôi đã làm:

importent: Mã này là bên trong một Bean với tất cả ý nghĩa của nó

@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; 
} 

Với giải pháp này trong trường hợp tôi không tìm thấy các tập tin tôi thực sự sẽ không viết các tập tin 2 lần cũng như bất kỳ tập tin khác như tôi đang đồng bộ hóa toàn bộ khối cho tất cả các chủ đề cố gắng để đạt được nó ngay cả khi là để viết một tập tin khác nhau.

Mọi đề xuất?

Cảm ơn.

+1

Phiên bản Java nào? – erickson

Trả lời

1

Điều gì tạo ra một mã khóa HashMap? Khóa sẽ là đường dẫn tệp và giá trị sẽ chỉ là một đối tượng được sử dụng làm khóa. Hãy nói rằng bản đồ này được định nghĩa như thế này:

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

Và đây là việc sử dụng:

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

Đường dẫn tệp là động. tôi không thể tạo ra một chìa khóa/đối tượng trên bay và khóa nó ... nó có tiềm năng điều kiện chủng tộc tương tự. khi tôi khóa đối tượng, chủ đề sau đây sẽ thay thế nó bằng một cái mới – Gleeb

+0

Hãy xem mã của tôi, tôi nghĩ nó giải quyết tất cả các điều kiện chủng tộc. Ít nhất là những gì tôi có thể nghĩ đến. – Avi

+0

Vẫn còn một số chờ đợi cho tất cả các tệp. Nhưng phần quan trọng ban đầu bị khóa trên mỗi tệp. Các hoạt động bảng 'khóa' không tốn kém (trong thời gian xử lý) – Avi

5

Tương tự như @ giải pháp Avi nhưng sử dụng một 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

giải pháp của bạn tạo đối tượng mới mỗi khi tồn tại tệp thời gian được truy vấn, vì vậy nó không phải lúc nào cũng tốt hơn giải pháp @ Avi. –

Các vấn đề liên quan