Implementing Runnable vs. extending Thread
为什么实现runnable比从线程类扩展更好?
实际需要解决的问题是,在任何有问题的情况下,工具总是首选于扩展。
扩展将两个类文件绑定得非常紧密,可能会导致一些代码处理非常困难。
当我第一次"理解"OO编程时,我扩展了所有东西,但它把我的整个设计变成了糊状。现在我只扩展了几个明显通过了"is-a"测试的东西,其他的东西都是一个接口…
许多问题刚刚停止发生(混淆了多个继承情况,浪费了时间重构层次结构,倾向于有"受保护"的变量,然后想知道当您在当前类中没有更改它们时,为什么它们会发生更改,链接构造函数的需求,弄清楚不同的继承树如何与彼此,…
似乎每三年(过去的20年)我都会觉得自己真的"得到"了编程,并且回顾了三年前我羞愧地做的蠢事……这就是其中的一个例子(但从近7年前的这一点来看)
这样可以将计算(what)与执行(when和/或how)分离。
例如,使用
1 2 3 4 5 6 7 | pool = Executors.newFixedThreadPool(poolSize); ... pool.execute(new Handler(serverSocket.accept())); ... class Handler implements Runnable { ... } |
使用
因为IS-A真的不是你想要的。您的类希望能够运行,但IS-A线程感觉太强。继承就是这么说的。您只需要实现run()方法,而不是线程类中的所有其他attendent方法。
这符合Scott Meyers在"更有效的C++"中提出的非常好的建议:使非叶类抽象化。替换接口,您就可以使用了。
您可能更喜欢实现可运行的接口来扩展类线程的原因如下:
- 减少后续上下文中的开销(源代码)
When you extends Thread class, each of your thread creates unique
object and associate with it. When you implements Runnable, it shares
the same object to multiple threads.
号
资料来源:博客-我不太确定这是否正确
- 可以通过可运行的网络发送任务(线程不可序列化,源)
- 更好的OOP风格
- 很可能你没有"是"的关系
- 您有可能扩展其他类(Java没有多重继承)
在继承层次结构中,扩展
使用
首先回答问题:
如果扩展线程,类(扩展线程)的实例将始终调用超类线程的构造函数。所以myClass myClass=新建myClass()将始终在实例化线程的MyClass的构造函数内调用"super()",最后,您可能会在类中实现一些开销(如果不使用超类线程的任何方法)。因此,只实现runnable允许类更快地运行,而不需要任何继承的开销。
此外,这里还有一些错误的答案:
Now I extend just the few things that clearly and obviously pass the"is-a" test and everything else is an interface...
号
你没有考虑过创建一个没有任何接口的对象吗?因为为每个对象实现一个接口是非常错误的!
When you extends Thread class, each of your thread creates unique object and associate with it. When you implements Runnable, it shares the same object to multiple threads.
号
错误,每次调用类的构造函数时,都会得到一个自己的对象,从哪里扩展或实现什么都不重要!
结论:在Java中,每个类实例都是一个对象,并且扩展类对象(而基元不是)。只有INTIN[IN]类的原语数组扩展了对象,这样的数组具有与任何对象相同的方法,但遗憾的是它们没有在JavaDoc中提到。太阳人可能不想让我们用它们)。
顺便说一句,继承至少有两个优点:代码共享和清晰的javadoc。因为如果从类继承,您可以看到JavaDoc中的所有子类。你也可以通过一个接口来实现,但是你不能共享代码。更重要的是,您将需要创建"嵌套"对象,并调用两个或多个对象的构造函数,而不是只调用一个,这再次意味着您将从超类对象本身实现一些开销!因为Java中没有对象,没有开销,尽可能少地创建对象对于高性能应用来说是非常重要的。物体是最伟大的,但不必要的物体不是…