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