public class Test {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
private static class Task implements Runnable {
public void run() {
try {
System.out.println(sdf.parse("2016-03-21 12:00:00").getTime());
} catch (ParseException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Task task = new Task();
Thread t1 = new Thread(task);
t1.start();
Thread t2 = new Thread(task);
t2.start();
Thread t3 = new Thread(task);
t3.start();
Thread t4 = new Thread(task);
t4.start();
Thread t5 = new Thread(task);
t5.start();
}
}
最近才知道,如果像上面代码那样通过定义静态共享的实例来使用SimpleDateFormat是会存在线程安全问题的。
例如线程被挂死:
或者转换的时间不对:
然后自己尝试读JDK源码来试图分析在SimpleDateFormat的代码中,究竟是哪里的函数或者代码会引起线程不安全,但是由于水平有限,最后还是找不出。
哪位大牛可以帮忙分析一下。
PS:我的jdk版本:1.8.0_73
ringa_lee2017-04-17 17:33:32
I took a look at the comments of the parse() source code, and there is a section by this guy
This parsing operation uses the {@link DateFormat#calendar
calendar} to produce a {@code Date}. All of the {@code
calendar}'s date-time fields are {@linkplain Calendar#clear()
cleared} before parsing, and the {@code calendar}'s default
values of the date-time fields are used for any missing
date-time information.
It probably means that the parse() method uses calendar to generate the returned Date instance. The problem is that the calendar it uses here is not a new one every time the method is executed. It defines a "protected Calendar calendar" attribute , according to the meaning of the comment, before each parse, all relevant attributes in the calendar will be cleared, and then the object will be filled with new processing results. In this case, in multi-threading, a thread will appear during the execution of parse() After setting the calendar, another thread cleared it. Because it is an sdf instance, other problems should be caused by this
PHP中文网2017-04-17 17:33:32
private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
// Convert input date to time field list
calendar.setTime(date);
boolean useDateFormatSymbols = useDateFormatSymbols();
...
}
The calendar used here is a class member, and multi-threading setTime will cause thread safety issues
伊谢尔伦2017-04-17 17:33:32
This has nothing to do with the implementation of SimpleDateFormat. It has to do with your multi-threaded use of the same object and failure to synchronize threads