三种方法解决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实例。如果使用不是很频繁时,可以使用此方法,这样可以降低创建新对象的开销。

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,这样的操作也会一定程度上影响性能。

个人最推荐的是第三种方法,那就是借助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); 
    }
 }

你可能感兴趣的:(三种方法解决SimpleDateFormat的线程不安全性)