SimpleDateFormat 是線程不安全的類,一般不要定義爲static變量,如果定義爲static,必須加鎖,或者使用DateUtils工具類。這是阿里java開發規範提到 的強制要求。爲何如此呢?
-
SimpleDateFormat 是非線程安全類,在使用過程中可能會造成安全問題。多線程調用parse方法剖出的異常:
-
DateTimeFormatter 顯示說明此類是不可變的且是線程安全的類。
-
SimpleDateFormat 的不安全使用:如果多個線程使用同一個SimpleDateFormat 的對象進行日期和字符串的轉化,則會有異常拋出。
-
所以如果使用SimpleDateFormat 在多線程下使用,則應該使用threadLocal,爲每一個線程構造一個對象。這樣就避免了多線程的競爭條件,從而可以安全使用。
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
- DateTimeFormatter 的parse爲何是線程安全的呢?由於它調用的parseResolved0 方法如下,可以看出這個方法的入參都是final 修飾的,不可變變量是線程安全的。
- DateTimeFormatter 的使用,通過如下測試也可看到結果。
-
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (int i = 0; i < 1000; i++) { new Thread(new Runnable() { @Override public void run() { TemporalAccessor parse = dateTimeFormatter.parse("2019-05-19 14:22:52"); LocalDateTime from = LocalDateTime.from(parse); Instant second = from.toInstant(ZoneOffset.ofTotalSeconds(0)); System.out.println(second); } }).start(); }