在一次項目上線的時候牡属,發(fā)現(xiàn)老是出現(xiàn)數(shù)據(jù)丟失問題渊涝,通過日志發(fā)現(xiàn)SimpleDateFormat是線程不安全的!E准啤哄孤!
代碼:
private static SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static Date string2DateTime(String dateStr) {
Date date = null;
try {
if (string != null && !string.trim().equals("")) {
date = dateTimeFormat.parse(string);
}
} catch (Exception e) {
logger.warn("字符串轉日期值失敗吹截!" + e.getMessage());
}
return date;
}
報錯:
2018-12-04 18:12:27.696 WARN pool-1-thread-9 128 [DateUtil.java:128] 字符串轉日期值失斒莩隆凝危!For input string: "E111133E2"
2018-12-04 18:12:27.696 WARN pool-1-thread-10 128 [DateUtil.java:128] 字符串轉日期值失敗晨逝!For input string: "E111133"
2018-12-04 18:12:27.696 WARN pool-1-thread-2 128 [DateUtil.java:128] 字符串轉日期值失敹昴!For input string: "E111133E2.11E2"
2018-12-04 18:12:27.696 WARN pool-1-thread-8 128 [DateUtil.java:128] 字符串轉日期值失斢交ā趴生!For input string: "E111133E2.11E22E2"
2018-12-04 18:12:27.696 WARN pool-1-thread-5 128 [DateUtil.java:128] 字符串轉日期值失敗昏翰!For input string: "E111133E2.11E22"
- 通過上述可見報錯日志可見苍匆,發(fā)生了類型轉換異常,debug發(fā)現(xiàn)傳入的參數(shù)dateStr是正確的時間參數(shù)棚菊,但是拋出了報錯日志中的錯誤浸踩。后來搜索發(fā)現(xiàn)是SimpleDateFormat是線程不安全的。
解決方案:
1. 將SimpleDateFormat定義成局部變量统求。
缺點:每調用一次方法就會創(chuàng)建一個SimpleDateFormat對象检碗,方法結束又要作為垃圾回收。
2.方法加同步鎖synchronized码邻,在同一時刻折剃,只有一個線程可以執(zhí)行類中的某個方法。
缺點:性能較差像屋,每次都要等待鎖釋放后其他線程才能進入怕犁。
3.使用第三方庫joda-time,由第三方考慮線程不安全的問題己莺。(可以使用)
4.使用ThreadLocal:每個線程擁有自己的SimpleDateFormat對象奏甫。(推薦使用)