農林漁牧網

您現在的位置是:首頁 > 畜牧業

2020 年,你還在使用 Java 中的 SimpleDateFormat 嗎?

2022-05-20由 CSDN 發表于 畜牧業

format方法怎麼用

2020 年,你還在使用 Java 中的 SimpleDateFormat 嗎?

作者 | 阿文

責編 | 屠敏

今天我和大家一起聊一聊SimpleDateFormat ,這都2020年了,怎麼還在用SimpleDateFormat ?

其實,作為一名Java 程式設計師,我們會經常在程式設計時候和時間打交道,比如要把某一個時間儲存到資料庫中去,而我們直接使用

Datedate = newDate();

System。out。println(date);

得到的時間都是這樣的

SunJun 07 17:22:52CST 2020

因此,我們經常需要把時間進行格式化處理,然後在進行儲存,方便閱讀。這個時候我們就會使用到SimpleDateFormat 類,比如使用下面的程式碼來獲取當前時間,並呼叫SimpleDateFormat 對時間進行格式化:

Date date = newDate();

SimpleDateFormat df = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);//設定日期格式

String datestr = df。format(date);

System。out。println(datestr);

最終輸出的時間為

2020-06-07 16:45:58

由於在java 8之前 SimpleDateFormat 是一個比較常用的類,但是我還是在這裡要建議開發者不要用 SimpleDateForma。原因有兩點:

首先,透過new 一個物件來操作物件,佔用記憶體大

,如果每處理一個時間資訊的時候,就需要new一個SimpleDateFormat例項物件,然後再丟棄這個物件。大量的物件就這樣被創建出來,佔用大量的記憶體和 jvm空間。

那麼很多人就會想,既然new 代價太大, 不如我們使用 static 將其設定為共享變數,這樣就可以減小頻繁建立物件帶來的記憶體開銷啦,真的是機智如我。

privatestatic SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

但是這樣操作在併發量非常大的情況下,由於 SimpleDateFormat 是執行緒不安全的,這也是第二點原因,這個在JDK文件中已經明確表明了SimpleDateFormat不應該用在多執行緒場景中:

Date formats are not synchronized。 It is recommended to create separate format instances for each thread。 If multiple threads access a format concurrently, it must be synchronized externally。

在《阿里巴巴 Java 開發手冊》中也明確表示不要定義SimpleDateFormat 為static 變數,如果定義static 必須要加鎖。

2020 年,你還在使用 Java 中的 SimpleDateFormat 嗎?

這背後的原因是由於 SimpleDateFormat 中的format方法在執行過程中,會使用一個成員變數calendar來儲存時間。

private StringBuffer format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) {

this。calendar。setTime(date);

boolean useDateFormatSymbols = this。useDateFormatSymbols();

int i = 0;

……

由於在宣告SimpleDateFormat的時候,使用的是static定義的。那麼這個SimpleDateFormat就是一個共享變數,SimpleDateFormat 中的calendar也就可以被多個執行緒訪問到。

舉個例子:假設一個執行緒A剛執行完calendar。setTime把時間設定成2020-05-07,這個執行緒還沒執行完,執行緒B又執行了calendar。setTime把時間改成了2020-06-07。這時候執行緒A繼續往下執行,拿到的calendar。getTime得到的時間就是執行緒B改過之後的。

除了format方法以外,SimpleDateFormat的parse方法也有同樣的問題。

所以,不要把SimpleDateFormat作為一個共享變數使用。

那麼如何解決這樣的問題呢?如果你使用的是Java 8 之前的JDK,那麼上面的《阿里巴巴Java 開發手冊》已經給出瞭解決方案,那就是使SimpleDateFormat 變成執行緒安全的,透過加鎖的方式來解決

privatestatic ThreadLocal threadLocal = new ThreadLocal() {

@Override

protected DateFormat initialValue(){

returnnew SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

}

};

而如果你使用的是Java 8 + 的版本,那麼你完全可以拋棄這種執行緒不安全的時間格式化方法。可以使用DateTimeFormatter代替SimpleDateFormat,這是一個執行緒安全的格式化工具類。

2020 年,你還在使用 Java 中的 SimpleDateFormat 嗎?

LocalDate 和LocalDateTime

Java 8開始,明確了日期時間概念,例如:瞬時(instant)、 長短(duration)、日期、時間、時區和週期。

同時繼承了Joda 庫按人類語言和計算機各自解析的時間處理方式。不同於老版本,新API基於ISO標準日曆系統,java。time包下的所有類都是不可變型別而且執行緒安全。

關鍵類

Instant:瞬時例項。

LocalDate:本地日期,不包含具體時間 例如:2014-01-14 可以用來記錄生日、紀念日、加盟日等。

LocalTime:本地時間,不包含日期。

LocalDateTime:組合了日期和時間,但不包含時差和時區資訊。

ZonedDateTime:最完整的日期時間,包含時區和相對UTC或格林威治的時差。

新API還引入了 ZoneOffSet 和 ZoneId 類,使得解決時區問題更為簡便。解析、格式化時間的 DateTimeFormatter 類也全部重新設計。

例如,我們使用LocalDate 代替Date,使用DateTimeFormatter 代替SimpleDateFormat,如下所示:

String DateNow = LocalDateTime。now()。format(DateTimeFormatter。ofPattern(“yyyy/MM/dd HH:mm:ss”)); // 當前日期和時間

System。out。println(DateNow);

這樣就避免了SimpleDateFormat 的執行緒不安全問題啦。