Java中的“实现可运行”与“扩展线程”

新手上路,请多包涵

从我在 Java 中使用线程的时间开始,我发现了以下两种编写线程的方法:

使用 工具 Runnable

 public class MyRunnable implements Runnable {
    public void run() {
        //Code
    }
}
//Started with a "new Thread(new MyRunnable()).start()" call

或者, 扩展 Thread

 public class MyThread extends Thread {
    public MyThread() {
        super("MyThread");
    }
    public void run() {
        //Code
    }
}
//Started with a "new MyThread().start()" call

这两个代码块有什么显着差异吗?

原文由 user65374 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 448
2 个回答

是的:IMO 实现 Runnable 是首选方法。您并没有真正专门化线程的行为。你只是给它一些运行的东西。这意味着 组合哲学 上“更纯粹”的方式。

_实际上_,这意味着您可以实现 Runnable 并从另一个类扩展……您还可以通过 Java 8 的 lambda 表达式实现 Runnable

原文由 Jon Skeet 发布,翻译遵循 CC BY-SA 4.0 许可协议

tl;dr:实现 Runnable 更好。但是,警告很重要

一般来说,我会建议使用类似 Runnable 的东西,而不是 Thread 因为它允许你只让你的工作与你选择的并发松散耦合。例如,如果您使用 Runnable 并且稍后决定这实际上不需要它自己的 Thread ,您可以只调用 threadA.run()。

警告: 在这里,我强烈反对使用原始线程。我更喜欢使用 CallablesFutureTasks (来自 javadoc:“A cancellable asynchronous computation”)。现代并发支持的超时、适当取消和线程池的集成对我来说都比一堆原始线程有用得多。

跟进: 有一个 FutureTask 构造函数,它允许您使用 Runnables(如果这是您最熟悉的)并且仍然可以获得现代并发工具的好处。 引用 javadoc

如果您不需要特定结果,请考虑使用以下形式的结构:

 Future<?> f = new FutureTask<Object>(runnable, null)

因此,如果我们将他们的 runnable 替换为您的 threadA ,我们将得到以下内容:

 new FutureTask<Object>(threadA, null)

另一个让您更接近 Runnables 的选项是 ThreadPoolExecutor 。您可以使用 execute 方法传入一个 Runnable 来执行“将来某个时间的给定任务”。

如果您想尝试使用线程池,上面的代码片段将变成如下所示(使用 Executors.newCachedThreadPool() 工厂方法):

 ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ThreadA());

原文由 Bob Cross 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题