Java 中的“实现 Runnable”与“扩展线程”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/541487/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:59:51  来源:igfitidea点击:

"implements Runnable" vs "extends Thread" in Java

javamultithreadingrunnableimplementsjava-threads

提问by user65374

From what time I've spent with threads in Java, I've found these two ways to write threads:

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

With implements Runnable:

implements Runnable

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

Or, with extends Thread:

或者,使用extends Thread

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

Is there any significant difference in these two blocks of code ?

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

采纳答案by Jon Skeet

Yes: implements Runnableis the preferred way to do it, IMO. You're not really specialising the thread's behaviour. You're just giving it something to run. That means compositionis the philosophically"purer" way to go.

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

In practicalterms, it means you can implement Runnableand extend from another class as well.

实践方面,它意味着你可以实现Runnable从另一个类扩展为好。

回答by Powerlord

I'm not an expert, but I can think of one reason to implement Runnable instead of extend Thread: Java only supports single inheritance, so you can only extend one class.

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

Edit: This originally said "Implementing an interface requires less resources." as well, but you need to create a new Thread instance either way, so this was wrong.

编辑:这最初是说“实现一个接口需要更少的资源”。同样,但是您需要以任何一种方式创建一个新的 Thread 实例,所以这是错误的。

回答by starblue

Instantiating an interface gives a cleaner separation between your code and the implementation of threads, so I'd prefer to implement Runnable in this case.

实例化接口可以更清晰地分离代码和线程的实现,因此在这种情况下我更愿意实现 Runnable。

回答by Bob Cross

tl;dr: implements Runnable is better. However, the caveat is important

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

In general, I would recommend using something like Runnablerather than Threadbecause it allows you to keep your work only loosely coupled with your choice of concurrency. For example, if you use a Runnableand decide later on that this doesn't in fact require it's own Thread, you can just call threadA.run().

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

Caveat:Around here, I strongly discourage the use of raw Threads. I much prefer the use of Callablesand FutureTasks(From the javadoc: "A cancellable asynchronous computation"). The integration of timeouts, proper cancelling and the thread pooling of the modern concurrency support are all much more useful to me than piles of raw Threads.

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

Follow-up:there is a FutureTaskconstructorthat allows you to use Runnables (if that's what you are most comfortable with) and still get the benefit of the modern concurrency tools. To quote the javadoc:

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

If you don't need a particular result, consider using constructions of the form:

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

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

So, if we replace their runnablewith your threadA, we get the following:

因此,如果我们将它们替换runnable为您的threadA,我们将得到以下信息:

new FutureTask<Object>(threadA, null)

Another option that allows you to stay closer to Runnables is a ThreadPoolExecutor. You can use the executemethod to pass in a Runnable to execute "the given task sometime in the future."

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

If you'd like to try using a thread pool, the code fragment above would become something like the following (using the Executors.newCachedThreadPool()factory method):

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

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

回答by Fabian Steeg

You should implement Runnable, but if you are running on Java 5 or higher, you should not start it with new Threadbut use an ExecutorServiceinstead. For details see: How to implement simple threading in Java.

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

回答by Herms

One thing that I'm surprised hasn't been mentioned yet is that implementing Runnablemakes your class more flexible.

还没有提到让我感到惊讶的一件事是实现Runnable使您的类更加灵活。

If you extend thread then the action you're doing is always going to be in a thread. However, if you implement Runnableit doesn't have to be. You can run it in a thread, or pass it to some kind of executor service, or just pass it around as a task within a single threaded application (maybe to be run at a later time, but within the same thread). The options are a lot more open if you just use Runnablethan if you bind yourself to Thread.

如果您扩展线程,那么您正在执行的操作将始终在线程中。但是,如果您实施Runnable它,则不必如此。您可以在线程中运行它,或者将它传递给某种执行程序服务,或者只是将它作为单线程应用程序中的任务传递(可能稍后运行,但在同一线程中)。选项有很多更开放,如果你只需要使用Runnable比如果你绑定自己Thread

回答by Govula Srinivas

Separating the Thread class from the Runnable implementation also avoids potential synchronization problems between the thread and the run() method. A separate Runnable generally gives greater flexibility in the way that runnable code is referenced and executed.

将 Thread 类与 Runnable 实现分离还避免了线程和 run() 方法之间潜在的同步问题。单独的 Runnable 通常在引用和执行可运行代码的方式上提供更大的灵活性。

回答by panzerschreck

Moral of the story:

故事的道德启示:

Inherit only if you want to override some behavior.

仅当您想覆盖某些行为时才继承。

Or rather it should be read as:

或者更确切地说,它应该被理解为:

Inherit less, interface more.

少继承,多接口。

回答by n13

Runnable because:

可运行,因为:

  • Leaves more flexibility for the Runnable implementation to extend another class
  • Separates the code from execution
  • Allows you to run your runnable from a Thread Pool, the event thread, or in any other way in the future.
  • 为 Runnable 实现提供更大的灵活性以扩展另一个类
  • 将代码与执行分开
  • 允许您从线程池、事件线程或将来以任何其他方式运行您的可运行对象。

Even if you don't need any of this now, you may in the future. Since there is no benefit to overriding Thread, Runnable is a better solution.

即使您现在不需要这些,将来也可能需要。由于覆盖 Thread 没有任何好处,Runnable 是一个更好的解决方案。

回答by Bart van Heukelom

I would say there is a third way:

我想说还有第三种方式:

public class Something {

    public void justAnotherMethod() { ... }

}

new Thread(new Runnable() {
   public void run() {
    instanceOfSomething.justAnotherMethod();
   }
}).start();

Maybe this is influenced a bit by my recent heavy usage of Javascript and Actionscript 3, but this way your class doesn't need to implement a pretty vague interface like Runnable.

也许这有点受到我最近大量使用 Javascript 和 Actionscript 3 的影响,但是这样您的类就不需要实现像Runnable.