歡迎您光臨本站 註冊首頁

Java SimpleDateFormat線程安全問題原理詳解

←手機掃碼閱讀     limiyoyo @ 2020-06-04 , reply:0

今天看資料偶然發現SimpleDateFormat居然不是線程安全的,平時使用時根本沒有考慮,萬幸今天發現了這個問題,得把寫的代碼得翻出來整理一下了。

一般我們使用的SimpleDateFormat一般是這樣寫的:

 public void method() { ... DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = dateFormat.parse("2020-05-10 19:53:00"); ... }


這樣寫完全沒有任何問題,但我們有時候會覺得重複創建SimpleDateFormat耗費性能,就想到把SimpleDateFormat對象做為類的靜態成員變量,那麼代碼就是這樣了:

 private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public void method() { ... Date date = dateFormat.parse("2020-05-10 19:53:00"); ... }


我經常在Controller做日期轉換的時候就是這麼幹的,但這樣寫很有問題,多線程通知執行容易出問題,要麼轉換後的結果不對,要麼報錯,我們測試一下:

 public class DateUtils { private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static Date prase(String date) throws ParseException { return dateFormat.parse(date); } static class Job extends Thread { @Override public void run() { try { System.out.println(this.getName() + ":" + DateUtils.prase("2020-05-10 19:53:00")); } catch (ParseException e) { } } } public static void main(String[] args) { for (int i = 0; i<10; i++) { new Job().start(); } } }

測試結果如下:

那有沒有好的解決方案呢,既不用重複創建對象,又保證線程安全呢?答案是有。

方法一:使用ThreadLocal

 public class MyController { private static ThreadLocallocal = new ThreadLocal() { protected DateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); }; }; public void method() { ... Date date = local.get().parse("2020-05-10 19:53:00"); ... } }


方法二:使用第三方apache提供工具包commons-lang3

 import org.apache.commons.lang3.time.FastDateFormat; public class MyController { public void method() { ... Date date = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss").parse("2020-05-10 19:53:00"); ... } }


推薦使用第二種,既快有方便。


[limiyoyo ] Java SimpleDateFormat線程安全問題原理詳解已經有255次圍觀

http://coctec.com/docs/java/show-post-236904.html