2

有人可以解释一下为什么执行此程序后的输出如此不同吗?

首先,类:Thread扩展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 在第二种情况下不能运行?

4

3 回答 3

4

第二种情况 ( threadA.run()) : -

由于threadA是类型的引用UsingThreadExtension:-

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

所以像这样调用runthreadA上的方法: -

threadA.run();

只会在线程中执行run方法。因此,线程的名称在第二个输出中是main in 。UsingThreadExtension0 main, 1 main, etc.


第一种情况 ( threadB.run()) : -

因为threadB是类型的引用,只Thread指向一个实例Thread

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()你会看到大量的日志记录。

在方法被直接覆盖的extends Thread情况下,这个空检查被绕过了。run()

于 2012-12-04T20:03:24.830 回答