2

誰かが私にこのプログラムの実行後の出力がとても異なる理由を説明できますか?

まず第一に、クラス:java.lang.Threadを拡張するスレッド

public class UsingThreadExtension extends Thread {

    public UsingThreadExtension(String s) {
        super(s);
    }

    @Override
    public void run() {
        for (int i=0; i<5; i++) {
            System.out.println(i + " " + Thread.currentThread().getName());

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

java.lang.Runnableの実装:

public class UsingRunnableImplementation implements Runnable {

    @Override
    public void run() {
        for (int i=0; i<5; i++) {
            System.out.println(i + " " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
     }
}

そしてメインクラス:

public class ThreadsExample {

    public static void main(String[] args) {
        UsingThreadExtension threadA = new UsingThreadExtension("Thread A");
        UsingRunnableImplementation runnableImplementation = new UsingRunnableImplementation();
        Thread threadB = new Thread(runnableImplementation, "Thread B");

        //threadA.start();
        threadB.start();

        try {
            //threadA.join();
            threadB.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //threadA.run();
        threadB.run();

        System.out.println("Main thread says hello!");
    }
}

この組み合わせでは、出力は次のようになります。

0 Thread B

1 Thread B

2 Thread B

3 Thread B

4 Thread B

Main thread says hello!

そして、threadBの部分にコメントを付け、threadAのコメントを外した後、次のようなものがあります。

0 Thread A

1 Thread A

2 Thread A

3 Thread A

4 Thread A

0 main

1 main

2 main

3 main

4 main

Main thread says hello!

誰かが私に言うことができます、正確にそのような違いを引き起こすのは何ですか?ヒントをいただければ幸いです。私はそれがthreadAのjava.lang.Thread.run()メソッドのオーバーライドに関連していると思いますが、なぜthreadBは2番目のケースで実行可能に実行されないのですか?

4

3 に答える 3

4

2 番目のケース ( threadA.run()) : -

threadAはタイプの参照であるためUsingThreadExtension: -

UsingThreadExtension threadA = new UsingThreadExtension("Thread A");

したがって、次のrunように threadA でメソッドを呼び出します: -

threadA.run();

メインスレッドでのみrunメソッドを実行します。したがって、スレッドの名前は2 番目の出力でメインになります。UsingThreadExtension0 main, 1 main, etc.


最初のケース ( threadB.run()) : -

sincethreadBはonly のインスタンスを指す型の参照です。ThreadThread

Thread threadB = new Thread(runnableImplementation, "Thread B");

したがって、次のようにrunメソッドを呼び出します。

threadB.run();

Thread クラスでオーバーライドされたrun()メソッドをスレッドのみで再度実行します。しかし、Thread クラスのrun()メソッドは実際には何も出力しないためです。したがって、 の出力は得られませんでした。mainthreadB.run()

于 2012-12-04T19:03:51.167 に答える
3

Runnable.run()新しいスレッドを開始するのではなく、他のメソッドと同様にメソッドを実行するだけです。新しいスレッドをスピンオフしたい場合は、常に使用する(またはエグゼキューターにThread.start()送信する) 必要があります。Runnable

于 2012-12-04T18:56:34.353 に答える
0

インスタンスをThread渡すと、Runnableそのインスタンスがプライベート フィールドに格納されます。のデフォルトのrun()方法java.lang.Threadは基本的に

if(target != null) target.run();

おそらく、スレッド B のケースで何が起こるかというとstart()、スレッドであり、スレッドが完了すると、内部的にtarget = null. その後、後でスレッドのrun()メソッドを呼び出すと、ターゲットへの参照がなくなるRunnableため、実行されません。

逆に、最初run()にメイン スレッドで呼び出し、後で呼び出すと、start()両方のログが大量に表示されます。

メソッドが直接オーバーライドされる場合、この null チェックはバイパスされますextends Threadrun()

于 2012-12-04T20:03:24.830 に答える