2

printStackTrace()入力を待った後、独自のスレッドで実行されているかのように動作します。これが私のコードです:

try {
    new Scanner(System.in).nextLine();
    throw new Exception();
} catch (Exception e) {
    e.printStackTrace();
}
System.out.print("STUFF");

期待される出力が得られることもありますが (STUFF最後に)、次のようになることもあります。

blabla // the scanner input
java.lang.ExceptionSTUFF
    at Test.main(Test.java:7)

そして時々これ:

blabla
java.lang.Exception
STUFF   at Test.main(Test.java:7)

スキャナを に置き換えてもSystem.in.read()、同じ結果が得られます。行を完全に削除すると、期待される結果が得られます。この問題に気付いた実際のプログラムでは、スタック トレースがはるかに長く、STUFF出力は常に期待どおり、または上記の 2 番目の出力 (2 行目の先頭) のように表示されました。

何が原因で、どうすれば解決できますか?

4

3 に答える 3

1

これは実際にはまったく奇妙な動作ではありません。Java は、このように動作するように設計されています。ほとんどの場合、これは私たちが実際に書いたよりも効率的にコードを実行できるようにする、誰もが好む機能です。そして、「それ」が意味するのは、JVM はコードを再配置して最適化するように設計されているということです。

このように少し見ることができます。Java は、可能な限り最も効率的な方法 (少なくともプログラムされていること) で、必要なことを実行するコード全体で使用している一種のフレームワークです。Java API は、私たちが使用している Java フレームワークへの API です。

そして、これをコードに結び付けます。2 つのストリーム、2 つのバッファリングされたストリーム、1 つはSystem.out、もう 1つは を初期化していますprintStackTrace()。コードを実行すると、Java はコードを再配置し、スレッド化して、Java が可能な限り最適に実行できるようにします。これは、最初に完了したストリームがコンソールに出力されることを意味します。

Java は、いつ出力されるかには価値がありません。それは私たち人間が持っている価値です。私たちは特別な順序で物事を読むことを好みます。そのため、いつ実行されるかを気にしないスレッドセーフなコードを作成することは、私たち開発者にとって Java が課題となっています。同じ入力が与えられた場合、常に同じ出力を返す必要があります。

System.outストリームはスタック トレース ストリームよりも高速に出力されるため、ストリームはバッファリングされているため、スタック トレースよりも先に出力される可能性があります。バッファリングされたストリームは、バッファリングに時間がかかります。これは、スレッド化と異なる時間の消費の両方です。Java が最初に実行されたストリームを提供して、そのスレッドと CPU を解放しないのはなぜですか?

解決:

どれがいつ印刷されるかが問題にならないような方法でコードを設計することにより、これに対抗するようにしてください。

于 2015-07-07T12:55:26.587 に答える
0

これは、コンソールに出力する性質です。標準出力、標準エラーなどすべてがコンソールに出力されるようにスプールされますが、Java は本質的にマルチスレッドであるため、これらの項目が出力のためにキューに追加される順序について保証はありません。

マルチスレッドはファンキーなことをすることができます!

于 2015-07-07T12:02:01.927 に答える