SimpleDateFormat的线程不安全性

来源:互联网 发布:ubuntu 16.04网络配置 编辑:程序博客网 时间:2024/06/06 02:11

线程安全性:
一个类是线程安全的是指在被多个线程访问时,类可以持续进行正确的行为.不用考虑这些线程运行时环境下的调度和交替.

三种方法解决SimpleDateFormat的线程不安全性
在Java项目中,我们通常会自己写一个DateUtil类,处理日期和字符串的转换。如下
public class DateUtil{
 private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
 public static formatDateToYYYYMMDDStr(Date date){ 
  return sdf.format(date);
 }
 public static formatYYYYMMDDStrToDate(String str){    
  return sdf.parse(str);
 }
}
然而,由于SimpleDateFormat类不是线程安全的,所以在多线程的环境下,往往会出现意想不到的结果。

有三种方法可以解决以上问题。
1)每次使用时,都创建一个新的SimpleDateFormat实例。如果使用不是很频繁时,可以使用此方法,这样可以降低创建新对象的开销。
public class DateUtil{
 public static formatDateToYYYYMMDDStr(Date date){ 
  SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
  return sdf.format(date);
 }
 public static formatYYYYMMDDStrToDate(String str){    
  SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
  return sdf.parse(str);
 }
}
2)使用同步:
public class DateUtil{
 private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
 private Date parse(String dateStr) throws ParseException{
  synchronized (sdf){
   return sdf.parse(dateStr);
  }
 }  
 private String format(Date date){
  synchronized (sdf){
   return sdf.format(dateStr);
  }
 }
}
不过,当线程较多时,当一个线程调用该方法时,其他想要调用此方法的线程就要block,这样的操作也会一定程度上影响性能。

3)个人最推荐的是第三种方法,那就是借助ThreadLocal对象每个线程只创建一个实例。
public class DateUtil {
 private static final String DATE_FORMAT = "yyyyMMdd";
 @SuppressWarnings("rawtypes")
 private static ThreadLocal threadLocal = new ThreadLocal() {
  protected synchronized Object initialValue() {
   return new SimpleDateFormat(DATE_FORMAT);
  }
 };
 public static DateFormat getDateFormat() {
  return (DateFormat) threadLocal.get();
 }
 public static Date parse(String textDate) throws ParseException {
  return getDateFormat().parse(textDate);
 }
}

原创粉丝点击