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 Date} を生成します。すべての {@code
calendar} の日時フィールドは {@linkplain Calendar#clear()
cleared}、および {@code Calendar} のデフォルト
日時フィールドの値は、欠落している
日時情報。
一般的な意味は、parse() メソッドがカレンダーを使用して返される Date インスタンスを生成するということです。問題は、ここで使用されるカレンダーが、メソッドが実行されるたびに新しいものではないということです。これは、「保護されたカレンダー」カレンダーを定義します。コメントの意味によると、各解析の前に、カレンダー内の関連する属性がクリアされ、その後、オブジェクトに新しい処理結果が書き込まれます。この場合、マルチスレッドでは、 parse() を実行すると、カレンダーを設定した後、別のスレッドがそれをクリアします。これにより、他の問題が発生するはずです。
伊谢尔伦2017-04-17 17:33:32
これは SimpleDateFormat の実装とは何の関係もありません。複数のスレッドで同じオブジェクトを使用し、スレッドの同期に失敗することに関係しています。