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
parse() 소스코드의 주석을 살펴보니 이 사람이 쓴 부분이 있습니다
이 구문 분석 작업에서는 {@link DateFormat#calendar
를 사용합니다.
calendar}를 사용하여 모든 {@code
calendar}의 날짜-시간 필드는 {@linkplain Calendar#clear()
cleared}, {@code Calendar}의 기본값
누락된 항목에는 날짜-시간 필드의 값이 사용됩니다
날짜-시간 정보
일반적인 의미는 pars() 메서드가 반환된 Date 인스턴스를 생성하기 위해 달력을 사용한다는 것입니다. 문제는 여기서 사용하는 달력이 메서드가 실행될 때마다 새로운 달력이 아니라는 것입니다. " 속성입니다. 주석의 의미에 따라 각 구문 분석 전에 달력의 관련 속성이 지워지고 객체가 새로운 처리 결과로 채워집니다. 이 경우 멀티 스레드에서는 실행 중에 parse(), 달력을 설정한 후 다른 스레드가 이를 지웠습니다. sdf 인스턴스이기 때문에 이로 인해 다른 문제가 발생해야 합니다.
伊谢尔伦2017-04-17 17:33:32
이것은 SimpleDateFormat의 구현과 아무 관련이 없습니다. 여러 스레드에서 동일한 개체를 사용하고 스레드를 동기화하지 못하는 것과 관련이 있습니다