public static final SimpleDateFormat FORMATTER = new SimpleDateFormat ( pattern: "yyyy-MM-dd HH:mm:ss");
新增一个全局Static的DataFormatter,并使用该Formatter重新生成了数据时间会导致时间在高并发场景中出现异常
问题原因:
如果在使用SimpleDateFormat时,用static定义,那么SimpleDateFormat变成了共享变量。SimpleDateFormat中的calendar就可以被多个线程访问到。执行format()时会修改calendar值,而这个修改将有可能会影响到其他线程。
// Called from Format after creating a FieldDelegate
private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
// Convert input date to time field list
calendar.setTime(date);
...
}
问题解决方案
解决方案一:SimpleDateFormat作为局部变量使用,在多线程执行函数中New一个SimpleDateFormat,保证每个线程独享一个对象,这种方式可以解决并发带来的问题,但性能较差。
解决方案二:使用JDK8的DateTimeFormatter替代SimpleDateFormat,线程安全的来处理时间的格式化问题(推荐方案):
DateTimeFormatter类被final修饰,且内部无任何可变的共享变量存在,因而是线程安全的。
Patterns for Formatting and Parsing
Patterns are based on a simple sequence of letters and symbols. A pattern is used to create a Formatter using the ofPattern(String) and ofPattern(String, Locale) methods. For example, "d MMM uuuu" will format 2011-12-03 as '3 Dec 2011'. A formatter created from a pattern can be used as many times as necessary, it is immutable and is thread-safe.