main()メソッドがスレッドを介して起動された場合、なぜrun()が呼び出し階層の最上位に表示されないのですか?
他の人が述べているように、これは「メイン」スレッドが特別であるためです。これは、標準Thread
のクラスメカニズムではなく、Javaブートストラップコードを介して起動されます。はpublic static void main(String[] args)
常にネイティブコードのメインスレッドによって実行されます。
もう1つの説明は、実際にはrun()
メソッドがあるかもしれませんが、スタックフレームを構築する方法は、ユーザーを混乱させないために意図的にそれを隠しているということです。たとえば、new Thread(new Test())
thenを実行しているので、Test
クラスは実際には。target
内のフィールドThread
です。バックグラウンドThread
が開始されると、実際には次Thread.run()
のコードを持つを呼び出します。
public void run() {
if (target != null) {
target.run();
}
}
しかし、スタックフレームにThread.run()
メソッドがあるはずなのに、そこにメソッドが表示されることはありません。run()
ユーザーがスーパークラスでメソッドをオーバーライドした場合、メソッドはスタックフレームにありThread
ます。スタックフレーム出力を改善するために、JDKによって削除される可能性があります。
Javaでのマルチスレッド化は、run()を定義し、start()を呼び出すことによって行われます。
これは正しいですが、後世のために、コードに問題があることを認識することが重要だと思いました。Test
クラスは拡張する必要はありませんThread
が、代わりにを実装する必要がありますRunnable
。Thread
を実装しているので動作しますRunnable
。
コードを実装Runnable
して次のように変更する必要があります。
public class Test implements Runnable {
public static void main(String[] args) throws Exception {
new Thread(new Test()).start();
throw new RuntimeException("Exception from main thread");
}
public void run() {
throw new RuntimeException("Exception from child thread");
}
}
Thread
または、スレッドの開始方法を次のように拡張して変更します。上記のRunnable
パターンは、Test
スレッドが必要に応じて別のクラスを拡張できるようにするために推奨されます。
public class Test extends Thread {
public static void main(String[] args) throws Exception {
new Test().start();
throw new RuntimeException("Exception from main thread");
}
@Override
public void run() {
throw new RuntimeException("Exception from child thread");
}
}
何でこれが大切ですか?現在のコードは実際には2Thread
つのオブジェクトをインスタンス化していますが、そのうちの1つだけがstart()
編集され、バックグラウンドとして実行されていますThread
。次のようなバグが発生する可能性があります。
public class Test extends Thread {
public static void main(String[] args) throws Exception {
Test test = new Test();
new Thread(test).start();
// this is not interrupting the background thread
test.interrupt();