三種方法解決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); 
    }
 }
相關文章
相關標籤/搜索