从我在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时,它将同一对象共享给多个线程。

其他回答

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

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

您应该实现Runnable,但如果您在Java5或更高版本上运行,则不应该使用新线程启动它,而是使用ExecutorService。有关详细信息,请参阅:如何在Java中实现简单线程。

我会说实际任务与线程分离。在Runnable的情况下,我们可以将任务传递给线程、执行器框架等,而通过扩展Thread任务则与线程对象本身耦合。在扩展线程的情况下,无法执行任务隔离。这就像我们将任务烧成线程对象,就像IC芯片一样(更具体地说,不会得到任务的任何句柄)。

Thread和Runnable的主要区别在于:-线程类似于:Worker(执行Runnable)-可运行的类似于:作业(由线程执行)

Java不支持多重继承,所以如果您扩展Thread类,则不会扩展其他类。

例如:如果您创建一个applet,那么它必须扩展applet类,所以这里创建线程的唯一方法是实现Runnable接口