从我在Java中使用线程的时间来看,我发现了两种编写线程的方法:

使用可运行的机具:

public class MyRunnable implements Runnable {
    public void run() {
        //Code
    }
}
//Started with a "new Thread(new MyRunnable()).start()" call

或者,使用扩展线程:

public class MyThread extends Thread {
    public MyThread() {
        super("MyThread");
    }
    public void run() {
        //Code
    }
}
//Started with a "new MyThread().start()" call

这两个代码块有什么显著的区别吗?


当前回答

我发现使用Runnable是最有用的,因为上面提到的所有原因,但有时我喜欢扩展Thread,这样我就可以创建自己的线程停止方法,并直接在我创建的线程上调用它。

其他回答

我不是专家,但我能想到实现Runnable而不是扩展Thread的一个原因:Java只支持单一继承,因此只能扩展一个类。

编辑:这原本是说“实现一个接口需要更少的资源”,但无论如何都需要创建一个新的线程实例,所以这是错误的。

简单的说法是:如果你实现了接口,这意味着你正在实现它的所有方法,如果你扩展了类,你正在继承你选择的方法。。。在这种情况下,只有一个名为Run()的方法,因此更好地实现Runnable接口。。

您可以共同使用它们

例子:

public class A implements Runnable{

    @Override
    public void run() {


        while(true){
             System.out.println("Class A is running");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }}

    }

}



public class Test {

    public static void main(String[] args) {

        Thread myThread =new Thread(new A());// 1
        myThread.start();
        System.out.println(" executed after thread A");//will never be reached

    }

} 

是的:implements Runnable是首选的实现方式,IMO。你并没有真正专门研究线程的行为。你只是在给它一些东西。这意味着构图是哲学上“更纯粹”的方式。

实际上,这意味着您可以实现Runnable并从另一个类扩展。。。您还可以通过lambda表达式实现Runnable,如Java 8。

这在Oracle的“定义和启动线程”教程中进行了讨论:

你应该使用这些成语中的哪一个?第一个成语,使用Runnable对象更一般,因为Runnable对象可以子类线程以外的类。第二个成语更容易使用在简单的应用程序中,但受限于您的任务类必须是线程的后代。本课重点介绍第一节方法,它将Runnable任务与Thread对象分离执行任务的。这种方法不仅更加灵活,而且它适用于所涵盖的高级线程管理API后来

换句话说,实现Runnable将在类扩展线程以外的类的情况下工作。Java不支持多重继承。此外,在使用某些高级线程管理API时,无法扩展线程。扩展Thread的唯一方案是在一个将来不会更新的小应用程序中。实现Runnable几乎总是更好的,因为随着项目的增长,它更加灵活。设计更改不会产生重大影响,因为您可以在java中实现许多接口,但只能扩展一个类。