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.
Date formats 不是同步的,需要對每個單獨的線程創建各自的實例。如果多線程同時
使用同一個format的話,必須同步。
所以在使用SimpleDateFormat的時候就的特別注意,以下幾種方式是保證線程安全
的使用方式:
一,使用的時候才創建對象:
public static String formatDate(Date date)throws ParseException{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
return simpleDateFormat.format(date);
}
public static Date parse(String dateString)throws ParseException{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
return simpleDateFormat.parse(dateString);
}
由於每次都是新建的對象,則可避免線程共享出現線程安全問題,但是頻繁的創建銷燬對象開銷過大。
二,使用synchronized進行同步。
public static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
public static String formatDate(Date date)throws ParseException{
synchronized (SIMPLE_DATE_FORMAT){
return SIMPLE_DATE_FORMAT.format(date);
}
}
public static Date parse(String dateString)throws ParseException{
synchronized (SIMPLE_DATE_FORMAT){
return SIMPLE_DATE_FORMAT.parse(dateString);
}
}
由於同步所以線程安全,但是很明顯多個線阻塞性能不佳。
三,使用ThreadLocal。
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
}
};
public static String formatDate(Date date)throws ParseException{
return threadLocal.get().format(date);
}
public static Date parse(String dateString)throws ParseException{
return threadLocal.get().parse(dateString);
}
這種用法也是《阿里巴巴開發手冊》的推薦用法。
四,使用1.8新的線程安全的api
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss");
public static String formatDate(LocalDateTime date)throws ParseException{
return FORMATTER.format(date);
}
public static LocalDateTime parse(String dateString)throws ParseException{
return LocalDateTime.parse(dateString,FORMATTER);
}