2012-05-09 58 views
1

我編寫了一個服務來爲用戶在我的網站上動態上傳的圖像生成縮略圖。這是它的工作方式:在Java中同步對資源的訪問(Spring MVC)

獲取縮略圖:

  1. 檢查是否該縮略圖以前
  2. 被要求如果不是這樣,調整原始圖像所要求的大小,並將它緩存的硬盤驅動器上
  3. 返回硬盤驅動器上的縮略圖緩存

上傳另一張圖片:

  1. 檢查此圖像是否已在之前上傳(例如,用戶可以更新他的個人資料圖片,舊的可以刪除)
  2. 如果是的話,刪除舊的圖像
  3. 保存的所有縮略圖/覆蓋新上傳的圖像

的問題是點2.當用戶正在請求縮略圖時。如果兩個用戶在同一時間請求相同的縮略圖並且之前沒有調整大小,該怎麼辦?這兩個請求都會告訴服務器調整原始圖片的大小並將其保存在硬盤上。 這兩個請求都會嘗試在同一時間在硬盤驅動器上寫入相同的文件,從而導致明顯的訪問問題。

如何避免在Spring MVC中發生這種衝突?所有這些縮略圖邏輯是彈簧控制器內部管理是這樣的:

@RequestMapping("/images/{width:\\d{1,10}}x{height:\\d{1,10}}/{subject:.+}.{ext:png|gif|jpg|PNG|GIF|JPG}") 
public void thumbnail(HttpServletResponse response, 
        HttpServletRequest request, 
        @PathVariable("width") int width, 
        @PathVariable("height") int height, 
        @PathVariable("subject") String subject, 
        @PathVariable("ext") String ext) throws IOException 
{ 
    // ... 
} 
+0

你可以發佈服務代碼嗎?這聽起來像一個簡單的同步問題? – MikePatel

回答

1
  • 檢查文件是否存在。

  • 如果文件不存在:

    • 創建一個ReentrantLock的,並將其存儲在一個ConcurrentHashMap中,與該文件爲重點的路徑,使用putIfAbsent()方法。

    • 如果putIfAbsent()返回一個鎖,那麼在下面使用這個鎖。否則,使用您創建並存儲在地圖中的鎖。

    • 獲取ReentrantLock上的鎖定。

    • 一旦你鎖定了,檢查文件是否存在。如果沒有,請創建它。否則,你沒有任何事情要做,因爲一個併發線程在之前創建了它。

    • 釋放鎖並將其從地圖中移除(在finally塊中)。

  • 閱讀文件,並返回其內容。