4

スレッドがスリープしないという問題があります。
ここにコード全体を入れることはできません。したがって、再現するために、ここに 5 秒待機する基本的なコードを示します。

try {
    int millisec = 5000;
    System.out.println(new Date());
    System.out.println("We wait " + millisec + " milliseconds");
    Thread.sleep(millisec);
    System.out.println(new Date());
} catch (Exception e) {
    e.printStackTrace();
}

出力:

Thu Aug 22 20:01:42 CEST 2013
5000 ミリ秒待機
Thu Aug 22 20:01:47 CEST 2013

全て大丈夫。
しかし、このコードをスレッドに入れると、スリープ状態になりません。このコードの例:

try {
    Thread aThread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                int millisec = 5000;
                System.out.println(new Date());
                System.out.println("We wait " + millisec + " milliseconds");
                Thread.sleep(millisec);
                System.out.println(new Date());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    aThread.start();
} catch (Exception e) {
    e.printStackTrace();
}

出力:

Thu Aug 22 20:07:30 CEST 2013
5000 ミリ秒待機

します。他には何もありません。スレッドは終了します。
理由がわかりません。アイデアはありますか?

編集: Eclipse と JUnit を使用してテストします。

4

2 に答える 2

5

編集:

問題は、JUnit がどのように機能するかであることが判明しました。バックグラウンド スレッドが生成されたことを認識しないため、テスト スレッドが完了すると、残りのスレッドを待たずに強制終了します。


main()小さなクラスで試してみると、コードは両方の日付行を適切に吐き出します。アプリケーションで出力が表示されない理由として、いくつかの可能性があります。

  • を生成しているスレッドはaThread、デーモン スレッド自体である可能性があります。したがってaThread、デーモンのステータスは生成スレッドのステータスから取得されるため、デーモンです。JVMが 2 番目より前System.out.println(...)に終了すると、は強制終了aThreadされます。それについて質問がある場合は、次のことを行う必要があります。

    Thread aThread = new Thread(new Runnable() {
    ...
    // ensure the deamon flag is off _before_ we start the thread
    aThread.setDaemon(false);
    aThread.start();
    
  • もう 1 つの可能性は、実際System.outには 2nd の前に何かが閉じていることですprintln(...);。可能性は低いですが、可能です。クリーンアップのためにシャットダウンフックを使用していますか?

  • 3 番目の可能性は、出力が実際に印刷されているのに、IDE またはコンソールに何らかの理由で出力が表示されていないことです。

  • もう 1 つの可能性は、 がSystem.out.println(...);を投げたことIOExceptionです。System.out.checkError()の値をチェックして、そうであるかどうかを確認するのは興味深いかもしれませんが、trueどのように表示するかはわかりません。

出力を印刷する代わりに、一時ファイルを作成してみてください。何かのようなもの:

new File("/var/tmp/" + System.currentTimeMillis()).createNewFile();

次に、"/var/tmp"(または OS の一時ディレクトリがある場所) に 2 つのファイルが表示されます。

System.outに変更しSystem.errて、何かが変わるかどうかを確認する必要もあります。疑わしいが試してみる価値がある。

これらがうまく機能しない場合は、何かが強制的に JVM を強制終了しているため、バックグラウンド スレッドを待つことができません。

于 2013-08-22T18:50:49.000 に答える
1

メイン スレッドで join() を呼び出さなかったと思います (JUnit を使用している場合は、テスト ケースを呼び出してスレッド オブジェクトを作成するスレッド)。

于 2013-08-23T02:29:25.663 に答える