Java 6线程 - 使用“implements Runnable”和“extends Thread”的不同行为

时间:2012-12-04 18:51:13

标签: java multithreading runnable java-6

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

首先,课程: 线程扩展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在第二种情况下不会运行runnable?

3 个答案:

答案 0 :(得分:4)

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

由于threadAUsingThreadExtension类型的引用: -

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

所以在threadA上调用run方法就像这样: -

threadA.run();

将仅在线程中执行UsingThreadExtension运行方法。因此,线程的名称在第二个输出的0 main, 1 main, etc.中是 main


第一个案例(threadB.run()): -

由于threadBThread类型的引用,仅指向Thread实例

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

因此,在其上调用 run 方法,如: -

threadB.run();

将仅在main线程中再次在 Thread类中执行 run()方法覆盖。但是由于 Thread类 run()方法实际上并没有打印任何东西。因此你没有获得threadB.run()的任何输出。

答案 1 :(得分:3)

Runnable.run()没有启动新线程,只是运行方法 - 就像任何其他方法一样。如果要分离新线程,则必须始终使用Thread.start()(或将Runnable提交给执行者)。

答案 2 :(得分:0)

当您构造Thread传递Runnable实例时,它会将该实例存储在私有字段中。 run()的默认java.lang.Thread方法基本上是

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

所以假设在你的线程B中发生的事情是你start()线程,并且当它在内部完成时{I} target = null。然后,当您稍后调用线程的run()方法时,它不再具有对目标Runnable的引用,因此不会运行它。

如果您反过来这样做,首先在主线程上调用run(),然后调用start(),您会看到大量的日志记录。

extends Thread情况下,直接覆盖run()方法,因此绕过此空检查。