分類
三種操作時間的方法都不是線程安全的
-
SimpleDateFormat類主要用於轉換格式,String←→Date;
-
Date類用於獲取毫秒數,或者設置Calendar對象的參數,date.getTime()、calendar.setTime(date)
-
Calendar類用於具體操作,比如獲取指定年、月的天數,加一年一月等。
線程安全
SimpleDateFormat 爲什麼是線程不安全的?
SimpleDateFormat類實現了 sdf.parse(dateStr), sdf.format(date)等時間轉化的方法,該類內部維護一個Calendar 全局變量
風險就出在Calendar 全局變量上,不同線程訪問該變量會造成線程安全問題
如果sdf是個static的,那麼多線程之間會共享sdf, 即共享這個Calendar引用,sdf.parse() 方法有如下的調用:
Date parse() {
calendar.clear(); // 清理calendar
... // 執行一些操作, 設置 calendar 的日期什麼的
calendar.getTime(); // 獲取calendar的時間
}
-
如果 線程A 調用了 sdf.parse(), 並且進行了 calendar.clear()後還未執行calendar.getTime(),線程B又調用了sdf.parse(), 這時候線程B也執行了sdf.clear()方法,這樣就導致線程A的的calendar數據被清空了(實際上A,B的同時被清空了).
-
或者當 A 執行了calendar.clear() 後被掛起,這時候B 開始調用sdf.parse()並順利i結束,這樣 A 的 calendar內存儲的的date,變成了後來B設置的calendar的date
解決辦法
- 可以使用局部變量
- 可以通過ThreadLocal包裹SimpleDateFormat全局變量(會爲每個線程創建一個副本,以空間換時間)