从我在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类是最好的。

最常见的区别是

当您扩展Thread类时,在此之后,您不能扩展所需的任何其他类。(如您所知,Java不允许继承多个类)。

当您实现Runnable时,您可以为您的类节省空间,以便将来或现在扩展任何其他类。

Java不支持多个继承,这意味着您只能在Java中扩展一个类,因此一旦扩展了Thread类,您就失去了机会,无法在Java中延伸或继承另一个类。在面向对象编程中,扩展类通常意味着添加新功能,以及修改或改进行为。如果我们没有对线程进行任何修改,那么请改用Runnable接口。可运行接口表示一个任务,它可以由普通线程或执行器或任何其他方式执行。因此,将Task逻辑分离为Runnable而不是Thread是一个很好的设计决策。将任务分离为可运行任务意味着我们可以重用任务,也可以通过不同的方式执行任务。因为一旦线程完成,就不能重新启动它。任务的Runnable与Thread,Runnable是赢家。Java设计器认识到这一点,这就是为什么Executors接受Runnable作为Task,并且他们有执行这些任务的工作线程。继承所有线程方法只是表示一个任务的额外开销,这可以通过Runnable轻松完成。

由javareviewed.blogspot.com提供

这是Java中Thread和Runnable之间的一些显著差异。如果您知道Thread与Runnable之间的其他差异,请通过评论分享。我个人在这个场景中使用Runnable over Thread,并建议根据您的需求使用Runnable或Callable接口。

然而,显著的区别是。

当您扩展Thread类时,每个线程都会创建一个唯一的对象并与其关联。当您实现Runnable时,它将同一对象共享给多个线程。

其他回答

如果我没有错的话,它或多或少类似于

接口和抽象类之间的区别是什么?

extends建立“Is A”关系,接口提供“Has A”功能。

首选工具可运行:

如果不需要扩展Thread类并修改Thread API默认实现如果你执行的是一个火灾和忘记命令如果您已经在扩展另一个类

首选“扩展线程”:

如果必须重写oracle文档页中列出的任何线程方法

通常,您不需要重写线程行为。因此,在大多数情况下,首选实现Runnable。

另一方面,使用高级ExecutorService或ThreadPoolExecutorServiceAPI提供了更多的灵活性和控制。

看看这个SE问题:

ExecutorService vs休闲线程生成器

您可以共同使用它们

例子:

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

    }

} 

如果使用runnable,则可以节省空间以扩展到任何其他类。

实例化接口在代码和线程的实现之间提供了更清晰的分离,因此在这种情况下我更希望实现Runnable。

线程类定义了几个可由扩展类重写的方法。但要创建线程,我们必须重写run()方法。这同样适用于Runnable。

然而,Runnable是创建线程的首选方法。主要原因如下:

由于Runnable是一个接口,因此可以扩展其他类。但如果您扩展“线程”,则该选项将消失。如果您没有修改或增强大量Thread功能,那么扩展Thread类不是首选方法。