SimpleDateFormat線程不安全測試

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)因爲是全局變量,創建的時候可能會創建多個實例,在關閉連接的時候,就可能只關閉了一個對象的連接,造成其他連接沒有被關閉,最後導致連接耗光系統不可用;

 

日期處理應該使用JDK8的日期API來替換Date、Calendar類了

JDK8 日期API :https://www.jianshu.com/p/f4abe1e38e09

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章