最近有一個開發的需求需要從服務器下載相關的照片憑證文件,服務器中需要先下載壓縮打包后供客戶下載。
邏輯思路是:
1.獲取數據庫中憑證的url
2.在服務器上根據對應的url下載圖片,寫入指定的文件夾(臨時創建)
3.壓縮整個文件夾並通過response返回給用戶
4.刪除臨時創建文件和文件夾
5.over
(說明:指定的文件夾是臨時創建的,不同的用戶創建的文件夾名字一致。)
-----------------------------------------------解決思路------------------------------------------------------------------
從需求中就可以看出代碼涉及了服務器上同一個文件夾的寫操作,如果多個用戶在差不多時刻點擊打包按鈕,那么有可能會產生沖突,需要進行多線程同步操作。大家都知道SpringMVC 的controller默認是單例模式,因此在controller中進行代碼同步操作是沒有問題的。
第一次是直接在controller的對應方法中加入了synchronized關鍵字。顯然這種做法是非常不負責任的,因為在controller中也會涉及數據庫的讀操作,這些操作是可以並發執行的。但是synchronized關鍵字會將整個controller方法變成同步方法,不同的線程需要排隊執行,降低了並發效率。
最好的方法是在相關的文件寫操作的地方進行
synchronized(this){
//FileIO operation
}
這就是細化同步代碼塊的粒度,減小原子大小,盡可能發揮線程並發的優勢。
ps:其實可以通過每個線程創建唯一目錄的形式去解決多線程沖突問題性能還更好,算是可以優化的地方吧,但是應用並發量小就不做考慮了。今天發現了問題做了一個記錄^_^