SimpleDateFormat
禁止定義成 static 變量或者全局共享變量,因爲它是線程不安全的,阿里巴巴的《Java開發手冊》:
爲什麼SimpleDateFormat
是線程不安全?
format
方法源碼:
可以看到 calendar
變量居然是全局變量,多線程情況下就會存在設置髒變量的情況。
所以,如果要用 SimpleDateFormat
,就在每次用的時候都創建一個 SimpleDateFormat
對象,做到線程間隔離;或者使用ThreadLocal:每個線程擁有自己的SimpleDateFormat對象。
使用線程池測試如下:
public class Demo2SimpleDateFormat {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
private static final ThreadLocal<SimpleDateFormat> ndf = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm"));
public static void main(String[] args) {
/**
* SimpleDateFormat線程不安全測試
*/
ExecutorService threadPool = Executors.newCachedThreadPool();
List<String> dateStrList = new ArrayList();
dateStrList.add("2020-06-11 10:00:01");
dateStrList.add("2020-06-12 11:00:02");
dateStrList.add("2020-06-13 12:00:03");
dateStrList.add("2020-06-14 13:00:04");
dateStrList.add("2020-06-15 14:00:05");
for (String s : dateStrList) {
threadPool.execute(() -> {
try {
Date date = ndf.get().parse(s);
// Date date = sdf.parse(s);
System.out.println(date);
TimeUnit.SECONDS.sleep(1);
} catch (ParseException | InterruptedException e) {
e.printStackTrace();
}
});
}
}
控制檯正常打印:
Mon Jun 01 10:00:00 CST 2020
Fri Jun 05 14:00:00 CST 2020
Wed Jun 03 12:00:00 CST 2020
Thu Jun 04 13:00:00 CST 2020
Tue Jun 02 11:00:00 CST 2020
定義成 static 變量或者全局共享變量後報錯:
總結:
1;全局變量使用中需要考慮多線程線程安全問題
2:慎用全局數字運算
3: 資源連接
資源連接包括數據庫連接、FTP連接、Redis連接等,這種也要慎用全局變量,一旦使用全局變量,就會遇到以下問題:
1)關閉連接的時候,就可能把別人正在操作的連接給關了,導致其他線程的業務中斷;
2)因爲是全局變量,創建的時候可能會創建多個實例,在關閉連接的時候,就可能只關閉了一個對象的連接,造成其他連接沒有被關閉,最後導致連接耗光系統不可用;