错误详情
使用时间格式转换SimpleDateFormat方法的时候,用static修饰,并在处于多线程的情况下执行,结果出现各种报错信息
public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static Date parse(String stringDate) throws ParseException {
return sdf.parse(stringDate);
}
报错信息一
Exception in thread "1" Exception in thread "0" java.lang.NumberFormatException: multiple points
java.lang.NumberFormatException: multiple points
报错信息二
Exception in thread "0" Exception in thread "2" Exception in thread "1" java.lang.NumberFormatException: For input string: "255.E2552E"
java.lang.NumberFormatException: empty String
错误分析
SimpleDateFormat类内部有一个Calendar对象引用,它用来储存和这个SimpleDateFormat相关的日期信息,例如sdf.parse(dateStr),sdf.format(date) 诸如此类的方法参数传入的日期相关String,Date等等, 都是交由Calendar引用来储存的.这样就会导致一个问题如果你的SimpleDateFormat是个static的, 那么多个thread 之间就会共享这个SimpleDateFormat, 同时也是共享这个Calendar引用。 SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。
解决方法
方法1:加锁 (但是性能不太好,不推荐)
public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static synchronized Date parse02(String stringDate) throws ParseException {
return sdf.parse(stringDate);
}
方法2:ThreadLocal(为每个线程创建独立的格式实例,推荐)记得使用后remove
public static final ThreadLocal<SimpleDateFormat> sdfThreadLocal = ThreadLocal.withInitial(()->new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public static Date parseThreadLocal(String stringDate) throws ParseException {
return sdfThreadLocal.get().parse(stringDate);
}
另:阿里Java开发手册中推荐,在jdk8中用DateTimeFormatter 代替 SimpleDateFormat