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);
}