SimpleDateFormat多執行緒下的異常
阿新 • • 發佈:2019-02-13
今天在生產上碰到一個怪異的問題,之前一直跑的很好的xml轉object程式,在日期轉化的過程中報錯的,經過排查原因,原來是由於SimpleDateFormat在多執行緒下執行造成的結果。
demo例子如下:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*日期格式化
**/
public class DateFormat {
private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd" );
public Date parseDate(String str ){
if(str == null)
return null;
try {
return SDF.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
public class Test {
public static void main (String[] args) {
for(int i=0;i<10;i++){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
DateFormat sdf = new DateFormat();
System.out.println(sdf.parseDate("2016-10-19"));
}
});
thread.start();
}
}
}
執行錯誤資訊:
Exception in thread "Thread-4" Exception in thread "Thread-3" java.lang.NumberFormatException: For input string: "..10011001EE22"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:430)
at java.lang.Long.parseLong(Long.java:483)
at java.text.DigitList.getLong(DigitList.java:194)
at java.text.DecimalFormat.parse(DecimalFormat.java:1316)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.busap.DateFormat.parseDate(DateFormat.java:14)
at com.busap.Abc$1.run(Abc.java:19)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "Thread-2" java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1110)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.busap.DateFormat.parseDate(DateFormat.java:14)
at com.busap.Abc$1.run(Abc.java:19)
at java.lang.Thread.run(Thread.java:745)
java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1110)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.busap.DateFormat.parseDate(DateFormat.java:14)
at com.busap.Abc$1.run(Abc.java:19)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "Thread-3" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:453)
at java.lang.Long.parseLong(Long.java:483)
at java.text.DigitList.getLong(DigitList.java:194)
at java.text.DecimalFormat.parse(DecimalFormat.java:1316)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.busap.DateFormat.parseDate(DateFormat.java:14)
at com.busap.Abc$1.run(Abc.java:13)
at java.lang.Thread.run(Thread.java:745)
各種異常接踵而至,原因就是SimpleDateFormat不是執行緒安全類。要想解決上述問題,去掉static final 修飾符,這樣每個執行緒生成一個SimpleDateFormat,執行緒之間互不影響就解決了上面的問題。不過如果在大併發的情況,就會生成一堆SimpleDateFormat類(static final 修飾符原意也是為了解決這個問題),為了優化大併發的情況,可以使用ThreadLocal。在同一個執行緒內共享一個SimpleDateFormat,總比多次呼叫生成多個的好。