实现Runnable接口与继承Thread类的区别

11

为什么实现Runnable接口比继承Thread类更好?

6个回答

19

重要的一点是,在任何有疑问的情况下,都应该优先使用implements而非extends。

extends会将两个类文件紧密地绑定在一起,并可能导致一些非常难以处理的代码。

当我首次“理解”面向对象编程时,我会对所有东西进行扩展,但这会使我的整个设计变得混乱。现在,我只扩展那些明显通过“is-a”测试的少数事物,其他所有内容都是接口...

许多问题就此停止发生(混淆的多重继承情况,时间浪费于重构层次结构,倾向于具有“protected”变量,然后想知道为什么它们在当前类中没有更改而又发生了变化,构造函数的链接要求,搞清楚不同继承树如何相互作用...)

似乎每3年(过去20年)我都认为我真正“掌握”了编程,并回顾我在3年前做的愚蠢事情感到羞愧... 这是其中之一(但距此时更近的是7年前)


9

这样,您可以将计算(即 what)与执行(即 when 和/或 how)分离。

使用 RunnableCallable,例如,您可以提交许多工作/计算给一个 Executor,它将负责安排这些任务。以下是来自 ExecutorService 的摘录:

pool = Executors.newFixedThreadPool(poolSize);
...
pool.execute(new Handler(serverSocket.accept()));
...
class Handler implements Runnable {
    ...
 }

使用Runnable/Callable比直接使用线程更加灵活。


还有,这样你的可运行类就可以扩展其他非Thread类。 - matt b

3
因为“IS-A”并不是您想要的。您的类希望成为Runnable,但“IS-A Thread”感觉太强了。这就是继承所说的。您真正想要的只是实现run()方法,而不是Thread类中的所有其他附属内容。
这符合Scott Meyers在《More Effective C++》中的非常好的建议:使非叶子类抽象化。使用接口进行替换,您就可以达到目标了。

2

如果您的继承层次结构中没有扩展Thread,那么这可能没有任何意义。只有在希望修改Thread功能时才扩展Thread

使用Runnable,任何继承层次结构中的类都可以公开一个任务,该任务可以被视为工作单元,以便由Thread执行。


2
你可能更喜欢实现接口Runnable而不是继承类Thread的原因如下:
- 在顺序上下文中,开销较小(来源)。 - 当你扩展Thread类时,每个线程都会创建唯一对象并与其关联。当你实现Runnable时,它将相同的对象共享给多个线程。 - 你可以使用Runnable通过网络发送任务(线程不可序列化,来源)。 - 更好的面向对象编程风格 - 很可能你没有一个“is a”关系。 - 你有扩展其他类的可能性(Java没有多继承)。

0

首先回答问题:

如果你扩展线程,你的类(扩展线程)的实例将始终调用超类线程的构造函数。因此, MyClass myclass = new MyClass() 将始终在MyClass的构造函数中调用“super()”,该构造函数实例化一个线程,并最终可以在类中实现一些开销(如果您不使用超类线程的任何方法)。因此,仅实现Runnable允许您的类在没有任何继承开销的情况下更快地运行。

此外,这里有一些错误的答案:

现在我只扩展那些明显通过“is-a”测试的少数内容,其他所有内容都是接口...

你从未考虑过创建一个没有任何接口的对象吗?因为为每个对象实现一个接口是非常错误的!

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

错误的,每次调用类的构造函数时,您都会获得自己的对象,无论它是从哪里扩展还是实现了什么!

结论:在Java中,每个类实例都是一个对象,并且扩展了类Object(而原始类型不是...只有原始类型数组如int[]类扩展了Object,并且这些数组具有与任何对象相同的方法-但遗憾的是它们没有在Javadoc中提到!Sun的人可能不希望我们使用它们)。

顺便说一下,继承至少有两个优点:代码共享和清晰的Javadoc。因为如果你从一个类继承,你可以在Javadoc中看到所有子类。你也可以用接口做到这一点,但是你不能共享代码。更重要的是,那样你就需要创建“嵌套”对象并调用两个或多个对象的构造函数,而不仅仅是一个对象,这又意味着你要实现一些来自超类Object本身的开销!因为在Java中没有没有开销的对象,尽可能地创建较少的对象对于高性能应用程序非常重要。对象是最好的东西,但不必要的对象不是...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接