ホームページ  >  に質問  >  本文

Java SImpleDateFormat线程安全问题

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

PHP中文网PHP中文网2764日前494

全員に返信(3)返信します

  • ringa_lee

    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() を実行すると、カレンダーを設定した後、別のスレッドがそれをクリアします。これにより、他の問題が発生するはずです。

    返事
    0
  • PHP中文网

    PHP中文网2017-04-17 17:33:32

    リーリー

    ここで使用されているカレンダーはクラスメンバーであり、マルチスレッドの setTime はスレッドの安全性の問題を引き起こします

    返事
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 17:33:32

    これは SimpleDateFormat の実装とは何の関係もありません。複数のスレッドで同じオブジェクトを使用し、スレッドの同期に失敗することに関係しています。

    返事
    0
  • キャンセル返事