Java 实现可运行与扩展线程

Java 实现可运行与扩展线程,java,Java,为什么实现Runnable比从Thread类扩展更好?通过这种方式,可以将计算(what)与执行(when和/或how)解耦 使用Runnable或Callable,您可以向执行者提交许多工作/计算,执行者将负责安排工作。以下是一份摘录表格: 使用Runnable/Callable比直接使用线程提供了更大的灵活性。在继承层次结构中,扩展Thread可能没有任何意义。如果要修改线程的功能,请仅扩展线程 使用Runnable,任何继承层次结构中的任何类都可以公开一个任务,该任务可以被视为一个工作单元

为什么实现Runnable比从Thread类扩展更好?

通过这种方式,可以将计算(what)与执行(when和/或how)解耦

使用
Runnable
Callable
,您可以向
执行者提交许多工作/计算,执行者将负责安排工作。以下是一份摘录表格:


使用
Runnable
/
Callable
比直接使用线程提供了更大的灵活性。

在继承层次结构中,扩展
Thread
可能没有任何意义。如果要修改
线程
的功能,请仅扩展
线程


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

,因为IS-a确实不是您想要的。您的类希望可以运行,但IS-A线程感觉太强了。继承就是这么说的。您实际上只想实现run()方法,而不是Thread类中的所有其他Attendant内容


这与Scott Meyers在“更有效的C++”中的非常好的建议是一致的:将非叶类抽象化。替换接口,您就找到了问题所在。

实际需要解决的问题是,在任何有问题的情况下,实现总是优先于扩展

Extends非常紧密地绑定了两个类文件,可能会导致一些非常难以处理的代码

当我第一次“理解”OO编程时,我扩展了所有东西,但它把我的整个设计变成了一堆乱七八糟的东西。现在,我只扩展了几个明显通过“is-a”测试的东西,其他一切都是一个接口

许多问题刚刚停止发生(混淆多重继承情况、浪费时间重构层次结构、倾向于“保护”然后,变量想知道为什么在当前类中没有更改它们时它们会更改,链接构造函数的需求,弄清楚不同的继承树如何相互作用


似乎每3年(过去20年)我都会“开始”编程,回顾3年前我羞愧地做过的蠢事……这是其中一个例子(但现在距离7年前不远)

您可能更喜欢实现以扩展的原因如下:

  • 减少顺序上下文中的开销(
扩展Thread类时,每个线程都会创建唯一的 对象并与其关联。当您实现Runnable时,它将共享 将同一对象复制到多个线程

资料来源:-我不太确定这是否正确

  • 您可以使用Runnable通过网络发送任务(线程不可序列化,)
  • 更好的OOP风格
    • 你很可能没有“是一种”的关系
    • 您可以扩展其他类(Java没有多重继承)

首先回答问题:

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

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

现在,我只扩展了几个明显通过“is-a”测试的东西,其他一切都是一个接口

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

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

错了,每次你调用一个类的构造函数,你都会得到一个自己的对象,不管它从哪里扩展或者实现了什么

结论:在java中,每个类实例都是一个对象,并扩展类对象(而原语不是…只有像int[]classes这样的原语数组扩展了对象,这样的数组与任何对象都有相同的方法-但遗憾的是,Javadoc中没有提到它们!Sun的家伙可能不希望我们使用它们)


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

这样您的runnable也可以扩展其他非线程类
pool = Executors.newFixedThreadPool(poolSize);
...
pool.execute(new Handler(serverSocket.accept()));
...
class Handler implements Runnable {
    ...
 }