问题描述:
最近有个需求上线后,对方反馈高并发时会出现下面两个报错:
1.系统异常:For input string: ""
2.系统异常:multiple points
失败后重新调用又能过去不报错了。我方检查报错时发现报错行如下所示:
// 全局变量
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private final SimpleDateFormat sdf2dT2 = new SimpleDateFormat("yyyyMMdd");
...
// 日期转换 ===报错行===
String date = sdf2dT2.format(sdf.parse(StartTime));
代码肯定是没问题的,经过高人指点,提示SimpleDateFormat是线程不安全的,问题原因找到。
附上SimpleDateFormat线程不安全详细说明:
DateFormat类中的Calendar对象被多线程共享,而Calendar对象本身不支持线程安全。
高并发之——SimpleDateFormat类的线程安全问题和解决方案_simpledateformat线程不安全-优快云博客
解决方法:
1.取消SimpleDateFormat全局变量,每次使用都new一个
String date = new SimpleDateFormat("yyyyMMdd").format(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(StartTime));
优点:改动小
缺点:不美观,浪费性能
2.使用Java8提供的DateTimeFormatter类
private static final DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter sdf2d = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private static final DateTimeFormatter sdf2dT2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// String转Date
public static Date formatDate(String inputDate, DateTimeFormatter sdfTarget){
return Date.from(LocalDate.parse(inputDate, sdfTarget).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}
// Date转String
public static String formatStr(Date inputDate, DateTimeFormatter sdfTarget){
return inputDate.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime()
.format(sdfTarget);
}
优点:合理,不浪费性能
缺点:改动稍大,不简洁