From what time I've spent with threads in Java, I've found these two ways to write threads:
从我在Java中使用线程的时间开始,我发现了这两种编写线程的方法:
With implements Runnable
:
使用实现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 ?
这两个代码块有什么显着差异吗?
41 个解决方案
#1
1477
Yes: implements Runnable
is 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 composition is the philosophically "purer" way to go.
是的:实现Runnable是首选方法,IMO。你并不是真正专注于线程的行为。你只是给它一些东西来运行。这意味着构图是哲学上“更纯粹”的方式。
In practical terms, it means you can implement Runnable
and extend from another class as well.
实际上,它意味着您可以实现Runnable并从另一个类扩展。
#2
502
tl;dr: implements Runnable is better. However, the caveat is important
tl; dr:实现Runnable更好。但是,警告很重要
In general, I would recommend using something like Runnable
rather than Thread
because it allows you to keep your work only loosely coupled with your choice of concurrency. For example, if you use a Runnable
and decide later on that this doesn't in fact require it's own Thread
, you can just call threadA.run().
一般来说,我建议使用像Runnable而不是Thread这样的东西,因为它允许你保持你的工作只与你选择的并发性松散耦合。例如,如果你使用Runnable并稍后决定这实际上不需要它自己的Thread,你可以调用threadA.run()。
Caveat: Around here, I strongly discourage the use of raw Threads. I much prefer the use of Callables and 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.
警告:在这里,我强烈反对使用原始线程。我更喜欢使用Callables和FutureTasks(来自javadoc:“可取消的异步计算”)。超时,正确取消和现代并发支持的线程池的集成对我来说比成堆的原始线程更有用。
Follow-up: there is a FutureTask
constructor that 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 runnable
with your threadA
, we get the following:
因此,如果我们用threadA替换他们的runnable,我们得到以下内容:
new FutureTask<Object>(threadA, null)
Another option that allows you to stay closer to Runnables is a ThreadPoolExecutor. You can use the execute method 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());
#3
233
Moral of the story:
故事的道德启示:
Inherit only if you want to override some behavior.
仅在您要覆盖某些行为时继承。
Or rather it should be read as:
或者更确切地说,它应该被理解为:
Inherit less, interface more.
继承少,界面更多。
#4
190
Well so many good Answers, i want to add more on this. This will help to understand Extending v/s Implementing Thread
.
Extends binds two class files very closely and can cause some pretty hard to deal with code.
那么多好的答案,我想在此添加更多。这将有助于理解扩展v / s实现线程。 Extends非常紧密地绑定两个类文件,并且可能导致一些非常难以处理的代码。
Both approaches do the same job but there have been some differences.
The most common difference is
两种方法都做同样的工作,但存在一些差异。最常见的区别是
- When you extends Thread class, after that you can’t extend any other class which you required. (As you know, Java does not allow inheriting more than one class).
- When you implements Runnable, you can save a space for your class to extend any other class in future or now.
当您扩展Thread类时,之后您无法扩展您需要的任何其他类。 (如您所知,Java不允许继承多个类)。
实现Runnable时,可以为类保存一个空间,以便将来或现在扩展任何其他类。
However, one significant difference between implementing Runnable and extending Thread is that
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.
但是,实现Runnable和扩展Thread之间的一个显着区别是,通过扩展Thread,每个线程都有一个与之关联的唯一对象,而实现Runnable时,许多线程可以共享同一个对象实例。
The following example helps you to understand more clearly
以下示例可帮助您更清楚地理解
//Implement Runnable Interface... class ImplementsRunnable implements Runnable {private int counter = 0;public void run() { counter++; System.out.println("ImplementsRunnable : Counter : " + counter); }}//Extend Thread class...class ExtendsThread extends Thread {private int counter = 0;public void run() { counter++; System.out.println("ExtendsThread : Counter : " + counter); }}//Use above classes here in main to understand the differences more clearly...public class ThreadVsRunnable {public static void main(String args[]) throws Exception { // Multiple threads share the same object. ImplementsRunnable rc = new ImplementsRunnable(); Thread t1 = new Thread(rc); t1.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread Thread t2 = new Thread(rc); t2.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread Thread t3 = new Thread(rc); t3.start(); // Creating new instance for every thread access. ExtendsThread tc1 = new ExtendsThread(); tc1.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread ExtendsThread tc2 = new ExtendsThread(); tc2.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread ExtendsThread tc3 = new ExtendsThread(); tc3.start(); }}
Output of the above program.
输出上述程序。
ImplementsRunnable : Counter : 1ImplementsRunnable : Counter : 2ImplementsRunnable : Counter : 3ExtendsThread : Counter : 1ExtendsThread : Counter : 1ExtendsThread : Counter : 1
In the Runnable interface approach, only one instance of a class is being created and it has been shared by different threads. So the value of counter is incremented for each and every thread access.
在Runnable接口方法中,只创建了一个类的一个实例,并且它已由不同的线程共享。因此,对于每个线程访问,计数器的值都会递增。
Whereas, Thread class approach, you must have to create separate instance for every thread access. Hence different memory is allocated for every class instances and each has separate counter, the value remains same, which means no increment will happen because none of the object reference is same.
而Thread类方法必须为每个线程访问创建单独的实例。因此,为每个类实例分配不同的内存,每个内存都有单独的计数器,值保持相同,这意味着不会发生任何增量,因为没有任何对象引用是相同的。
When to use Runnable?
Use Runnable interface when you want to access the same resource from the group of threads. Avoid using Thread class here, because multiple objects creation consumes more memory and it becomes a big performance overhead.
什么时候使用Runnable?如果要从线程组访问相同的资源,请使用Runnable接口。避免在这里使用Thread类,因为多个对象创建会占用更多内存,并且会成为很大的性能开销。
A class that implements Runnable is not a thread and just a class. For a Runnable to become a Thread, You need to create an instance of Thread and passing itself in as the target.
实现Runnable的类不是一个线程而只是一个类。要使Runnable成为线程,您需要创建一个Thread实例并将其自身作为目标传递。
In most cases, the Runnable interface should be used if you are only planning to override the run()
method and no other Thread methods. This is important because classes should not be subclassed unless the programmer intends on modifying or enhancing the fundamental behavior of the class.
在大多数情况下,如果您只计划覆盖run()方法而不使用其他Thread方法,则应使用Runnable接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应对类进行子类化。
When there is a need to extend a superclass, implementing the Runnable interface is more appropriate than using the Thread class. Because we can extend another class while implementing Runnable interface to make a thread.
当需要扩展超类时,实现Runnable接口比使用Thread类更合适。因为我们可以在实现Runnable接口的同时扩展另一个类来创建一个线程。
I hope this will help!
我希望这个能帮上忙!
#5
73
One thing that I'm surprised hasn't been mentioned yet is that implementing Runnable
makes 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 Runnable
it 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 Runnable
than if you bind yourself to Thread
.
如果你扩展线程,那么你正在做的动作总是在一个线程中。但是,如果您实现Runnable,则不必如此。您可以在一个线程中运行它,或者将它传递给某种执行器服务,或者只是作为单个线程应用程序中的任务传递它(可能在以后运行,但在同一个线程内)。如果你只使用Runnable,那么这些选项会比将你自己绑定到Thread更加开放。
#6
66
If you want to implements or extends any other class then Runnable
interface is most preferable other wise if you do not want any other class to extend or implement then Thread
class is preferable
如果你想实现或扩展任何其他类,那么如果你不希望任何其他类扩展或实现那么Runnable接口是最优选的,那么Thread类是更可取的
The most common difference is
最常见的区别是
When you extends Thread
class, after that you can’t extend any other class which you required. (As you know, Java does not allow inheriting more than one class).
当您扩展Thread类时,之后您无法扩展您需要的任何其他类。 (如您所知,Java不允许继承多个类)。
When you implements Runnable
, you can save a space for your class to extend any other class in future or now.
实现Runnable时,可以为类保存一个空间,以便将来或现在扩展任何其他类。
-
Java doesn't support multiple inheritance, which means you can only extend one class in Java so once you extended Thread class you lost your chance and can not extend or inherit another class in Java.
Java不支持多重继承,这意味着你只能在Java中扩展一个类,所以一旦你扩展了Thread类,你就失去了机会,无法在Java中扩展或继承另一个类。
-
In Object oriented programming extending a class generally means adding new functionality, modifying or improving behaviors. If we are not making any modification on Thread then use Runnable interface instead.
在面向对象的编程中,扩展类通常意味着添加新功能,修改或改进行为。如果我们不在Thread上进行任何修改,那么请改用Runnable接口。
-
Runnable interface represent a Task which can be executed by either plain Thread or Executors or any other means. so logical separation of Task as Runnable than Thread is good design decision.
Runnable接口表示一个Task,它可以由普通的Thread或Executor或任何其他方法执行。所以将Task作为Runnable与Thread进行逻辑分离是一个很好的设计决策。
-
Separating task as Runnable means we can reuse the task and also has liberty to execute it from different means. since you can not restart a Thread once it completes. again Runnable vs Thread for task, Runnable is winner.
将任务分离为Runnable意味着我们可以重用该任务,并且可以*地从不同的方式执行它。因为一旦完成就无法重启线程。再次Runnable vs Thread for task,Runnable是胜利者。
-
Java designer recognizes this and that's why Executors accept Runnable as Task and they have worker thread which executes those task.
Java设计者认识到这一点,这就是Executors接受Runnable作为Task的原因,他们有工作线程来执行这些任务。
-
Inheriting all Thread methods are additional overhead just for representing a Task which can be done easily with Runnable.
继承所有Thread方法只是用于表示可以使用Runnable轻松完成的Task的额外开销。
Courtesy from javarevisited.blogspot.com
礼貌来自javarevisited.blogspot.com
These were some of notable difference between Thread and Runnable in Java, if you know any other differences on Thread vs Runnable than please share it via comments. I personally use Runnable over Thread for this scenario and recommends to use Runnable or Callable interface based on your requirement.
这些是Java中Thread和Runnable之间的一些显着差异,如果你知道Thread vs Runnable上的任何其他差异,请通过评论分享。我个人在这种情况下使用Runnable over Thread,并建议根据您的要求使用Runnable或Callable接口。
However, the significant difference is.
但是,显着的区别是。
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.
当你扩展Thread类时,你的每个线程都会创建唯一的对象并与之关联。当你实现Runnable时,它会将同一个对象共享给多个线程。
#7
61
Actually, It is not wise to compare Runnable
and Thread
with each other.
实际上,将Runnable和Thread相互比较是不明智的。
This two have a dependency and relationship in multi-threading just like Wheel and Engine
relationship of motor vehicle.
这两者在多线程中具有依赖性和关系,就像机动车的车轮和发动机关系一样。
I would say, there is only one way for multi-threading with two steps. Let me make my point.
我想说,只有一种方法可以通过两个步骤实现多线程。让我说明我的观点。
Runnable:
When implementing interface Runnable
it means you are creating something which is run able
in a different thread. Now creating something which can run inside a thread (runnable inside a thread), doesn't mean to creating a Thread.
So the class MyRunnable
is nothing but a ordinary class with a void run
method.And it's objects will be some ordinary objects with only a method run
which will execute normally when called. (unless we pass the object in a thread).
Runnable:当实现接口Runnable时,它意味着你正在创建一个可以在不同线程中运行的东西。现在创建可以在线程内运行的东西(在线程内可运行)并不意味着创建一个Thread。所以类MyRunnable只不过是一个带有void run方法的普通类。它的对象将是一些普通的对象,只有一个方法运行,在调用时会正常执行。 (除非我们在一个线程中传递对象)。
Thread:class Thread
, I would say A very special class with the capability of starting a new Thread which actually enables multi-threading through its start()
method.
Thread:class Thread,我想说一个非常特殊的类,它具有启动一个新Thread的能力,它实际上通过start()方法实现了多线程。
Why not wise to compare?
Because we need both of them for multi-threading.
为什么不明智地比较?因为我们需要它们用于多线程。
For Multi-threading we need two things:
对于多线程,我们需要两件事:
- Something that can run inside a Thread (Runnable).
- Something That can start a new Thread (Thread).
可以在Thread(Runnable)中运行的东西。
可以启动新线程(线程)的东西。
So technically and theoretically both of them is necessary to start a thread, one will run and one will make it run (Like Wheel and Engine
of motor vehicle).
因此从技术上和理论上讲,它们都是启动螺纹所必需的,一个将运行,一个将使其运行(如机动车的车轮和发动机)。
That's why you can not start a thread with MyRunnable
you need to pass it to a instance of Thread
.
这就是为什么你不能用MyRunnable启动一个线程,你需要将它传递给一个Thread实例。
But it is possible to create and run a thread only using class Thread
because Class Thread
implements Runnable
so we all know Thread
also is a Runnable
inside.
但是有可能只使用类Thread来创建和运行一个线程,因为Class Thread实现了Runnable,所以我们都知道Thread也是一个Runnable。
Finally Thread
and Runnable
are complement to each other for multithreading not competitor or replacement.
最后,Thread和Runnable是多线程而不是竞争对手或替代者的补充。
#8
41
You should implement Runnable, but if you are running on Java 5 or higher, you should not start it with new Thread
but use an ExecutorService instead. For details see: How to implement simple threading in Java.
您应该实现Runnable,但是如果您在Java 5或更高版本上运行,则不应该使用新的Thread启动它,而是使用ExecutorService。有关详细信息,请参阅:如何在Java中实现简单线程。
#9
31
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实例,所以这是错误的。
#10
19
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那样实现一个非常模糊的界面。
#11
16
With the release of Java 8, there is now a third option.
随着Java 8的发布,现在有第三种选择。
Runnable
is a functional interface, which means that instances of it can be created with lambda expressions or method references.
Runnable是一个功能接口,这意味着可以使用lambda表达式或方法引用创建它的实例。
Your example can be replaced with:
您的示例可以替换为:
new Thread(() -> { /* Code here */ }).start()
or if you want to use an ExecutorService
and a method reference:
或者如果要使用ExecutorService和方法引用:
executor.execute(runner::run)
These are not only much shorter than your examples, but also come with many of the advantages stated in other answers of using Runnable
over Thread
, such as single responsibility and using composition because you're not specializing the thread's behaviour. This way also avoids creating an extra class if all you need is a Runnable
as you do in your examples.
这些不仅比您的示例短得多,而且还具有使用Runnable over Thread的其他答案中陈述的许多优点,例如单一责任和使用组合,因为您没有专门化线程的行为。如果你需要的只是一个Runnable,就像在你的例子中一样,这种方式也避免了创建一个额外的类。
#12
15
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。
#13
12
- Java doesn't support multiple inheritance, which means you can only extend one class in Java so once you extended
Thread
class you lost your chance and can not extend or inherit another class in Java. - In object-oriented programming extending a class generally means adding new functionality, modifying or improving behaviors. If we are not making any modification on
Thread
than useRunnable
interface instead. -
Runnable
interface represent aTask
which can be executed by either plainThread
orExecutors
or any other means. So logical separation ofTask
asRunnable
thanThread
is good design decision. - Separating task as
Runnable
means we can reuse the task and also has liberty to execute it from different means. Since you can not restart aThread
once it completes, againRunnable
vsThread
for task,Runnable
is winner. - Java designer recognizes this and that's why
Executors
acceptRunnable
asTask
and they have worker thread which executes those task. - Inheriting all
Thread
methods are additional overhead just for representing aTask
which can can be done easily withRunnable
.
Java不支持多重继承,这意味着你只能在Java中扩展一个类,所以一旦你扩展了Thread类,你就失去了机会,无法在Java中扩展或继承另一个类。
在面向对象的编程中,扩展类通常意味着添加新功能,修改或改进行为。如果我们不在Thread上进行任何修改而不是使用Runnable接口。
Runnable接口表示一个Task,它可以由普通的Thread或Executor或任何其他方法执行。因此,将Task作为Runnable与Thread进行逻辑分离是一个很好的设计决策。
将任务分离为Runnable意味着我们可以重用该任务,并且可以*地从不同的方式执行它。由于一旦完成就无法重新启动线程,再次运行Runnable vs Thread任务,Runnable就是胜利者。
Java设计者认识到这一点,这就是Executors接受Runnable作为Task的原因,他们有工作线程来执行这些任务。
继承所有Thread方法只是用于表示可以使用Runnable轻松完成的Task的额外开销。
#14
10
Runnable because:
- Leaves more flexibility for theRunnable implementation to extendanother class
- Separates the code fromexecution
- Allows you to run yourrunnable from a Thread Pool, theevent thread, or in any other way inthe future.
为theRunnable实现提供了更大的灵活性,以扩展其他类
分离代码fromexecution
允许您从线程池,事件线程或以后以任何其他方式运行您的运行。
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是一个更好的解决方案。
#15
10
Everyone here seems to think that implementing Runnable is the way to go and I don't really disagree with them but there is also a case for extending Thread in my opinion, in fact you have sort of demonstrated it in your code.
这里的每个人似乎认为实现Runnable是要走的路,我并不是真的不同意它们,但在我看来还有一个扩展Thread的案例,事实上你已经在你的代码中展示了它。
If you implement Runnable then the class that implements Runnable has no control over the thread name, it is the calling code that can set the thread name, like so:
如果实现Runnable,那么实现Runnable的类无法控制线程名称,它是可以设置线程名称的调用代码,如下所示:
new Thread(myRunnable,"WhateverNameiFeelLike");
but if you extend Thread then you get to manage this within the class itself (just like in your example you name the thread 'ThreadB'). In this case you:
但是如果你扩展Thread然后你就可以在类本身内管理它(就像在你的例子中你命名线程'ThreadB')。在这种情况下你:
A) might give it a more useful name for debugging purposes
A)可能会为调试目的提供一个更有用的名称
B) are forcing that that name be used for all instances of that class (unless you ignore the fact that it is a thread and do the above with it as if it is a Runnable but we are talking about convention here in any case so can ignore that possibility I feel).
B)强制该名称用于该类的所有实例(除非你忽略它是一个线程并使用它执行上面的操作,就好像它是一个Runnable但我们在这里谈论约定,所以可以忽略我觉得的那种可能性)。
You might even for example take a stack trace of its creation and use that as the thread name. This might seem odd but depending on how your code is structured it can be very useful for debugging purposes.
您甚至可以例如获取其创建的堆栈跟踪并将其用作线程名称。这可能看起来很奇怪,但根据代码的结构,它对调试非常有用。
This might seem like a small thing but where you have a very complex application with a lot of threads and all of a sudden things 'have stopped' (either for reasons of deadlock or possibly because of a flaw in a network protocol which would be less obvious - or other endless reasons) then getting a stack dump from Java where all the threads are called 'Thread-1','Thread-2','Thread-3' is not always very useful (it depends on how your threads are structured and whether you can usefully tell which is which just by their stack trace - not always possible if you are using groups of multiple threads all running the same code).
这可能看起来像一个小东西,但你有一个非常复杂的应用程序,有很多线程,突然之间“已经停止”(出于死锁的原因,或者可能是因为网络协议中的缺陷会少一些显然 - 或其他无限的原因)然后从Java获得堆栈转储,其中所有线程被称为'Thread-1','Thread-2','Thread-3'并不总是非常有用(它取决于你的线程如何结构化以及是否可以通过堆栈跟踪有用地告诉哪个是哪个 - 如果您使用的是多个线程的组都运行相同的代码,则不总是可行的。
Having said that you could of course also do the above in a generic way by creating an extension of the thread class which sets its name to a stack trace of its creation call and then use that with your Runnable implementations instead of the standard java Thread class (see below) but in addition to the stack trace there might be more context specific information that would be useful in the thread name for debugging (a reference to one of many queues or sockets it could processing for example in which case you might prefer to extend Thread specifically for that case so that you can have the compiler force you (or others using your libraries) to pass in certain info (e.g. the queue/socket in question) for use in the name).
说过你当然也可以通过创建一个线程类的扩展来以一般方式完成上述操作,该线程类将其名称设置为其创建调用的堆栈跟踪,然后将其与Runnable实现而不是标准java Thread类一起使用(参见下文)但除了堆栈跟踪之外,可能还有更多特定于上下文的信息,这些信息在调试的线程名称中很有用(对可以处理的许多队列或套接字之一的引用,例如在这种情况下您可能更喜欢特别针对该情况扩展Thread,以便您可以让编译器强制您(或其他使用您的库)传递某些信息(例如,有问题的队列/套接字)以便在名称中使用)。
Here's an example of the generic thread with the calling stack trace as its name:
以下是调用堆栈跟踪作为其名称的通用线程的示例:
public class DebuggableThread extends Thread { private static String getStackTrace(String name) { Throwable t= new Throwable("DebuggableThread-"+name); ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(os); t.printStackTrace(ps); return os.toString(); } public DebuggableThread(String name) { super(getStackTrace(name)); } public static void main(String[] args) throws Exception { System.out.println(new Thread()); System.out.println(new DebuggableThread("MainTest")); }}
and here's a sample of the output comparing the two names:
这是一个比较两个名称的输出样本:
Thread[Thread-1,5,main]Thread[java.lang.Throwable: DebuggableThread-MainTest at DebuggableThread.getStackTrace(DebuggableThread.java:6) at DebuggableThread.<init>(DebuggableThread.java:14) at DebuggableThread.main(DebuggableThread.java:19),5,main]
#16
10
Since this is a very popular topic and the good answers are spread all over and dealt with in great depth, I felt it is justifiable to compile the good answers from the others into a more concise form, so newcomers have an easy overview upfront:
由于这是一个非常受欢迎的话题,而且好的答案遍布各处并深入处理,我觉得将其他人的好答案汇编成更简洁的形式是合理的,因此新人有一个简单的概述:
-
You usually extend a class to add or modify functionality. So, if you don't want to overwrite any Thread behavior, then use Runnable.
您通常会扩展一个类来添加或修改功能。因此,如果您不想覆盖任何Thread行为,请使用Runnable。
-
In the same light, if you don't need to inherit thread methods, you can do without that overhead by using Runnable.
同样,如果您不需要继承线程方法,那么使用Runnable可以避免这种开销。
-
Single inheritance: If you extend Thread you cannot extend from any other class, so if that is what you need to do, you have to use Runnable.
单继承:如果扩展Thread,则无法从任何其他类扩展,因此如果您需要这样做,则必须使用Runnable。
-
It is good design to separate domain logic from technical means, in that sense it is better to have a Runnable task isolating your task from your runner.
将域逻辑与技术手段分开是一种很好的设计,从这个意义上说,让Runnable任务将你的任务与你的跑步者隔离开来是更好的选择。
-
You can execute the same Runnable object multiple times, a Thread object, however, can only be started once. (Maybe the reason, why Executors do accept Runnables, but not Threads.)
您可以多次执行相同的Runnable对象,但是,Thread对象只能启动一次。 (也许是原因,为什么Executors接受Runnables,但不接受Threads。)
-
If you develop your task as Runnable, you have all flexibility how to use it now and in the future. You can have it run concurrently via Executors but also via Thread. And you still could also use/call it non-concurrently within the same thread just as any other ordinary type/object.
如果您将任务开发为Runnable,那么您现在和将来都可以灵活使用它。您可以通过Executors同时运行它,也可以通过Thread运行它。而你仍然可以在同一个线程中非同时使用/调用它,就像任何其他普通类型/对象一样。
-
This makes it also easier to separate task-logic and concurrency aspects in your unit tests.
这使得在单元测试中分离任务逻辑和并发方面也变得更容易。
-
If you are interested in this question, you might be also interested in the difference between Callable and Runnable.
如果您对此问题感兴趣,您可能也对Callable和Runnable之间的区别感兴趣。
#17
8
This is discussed in Oracle's Defining and Starting a Thread tutorial:
这在Oracle的定义和启动线程教程中讨论:
Which of these idioms should you use? The first idiom, which employs a Runnable object, is more general, because the Runnable object can subclass a class other than Thread. The second idiom is easier to use in simple applications, but is limited by the fact that your task class must be a descendant of Thread. This lesson focuses on the first approach, which separates the Runnable task from the Thread object that executes the task. Not only is this approach more flexible, but it is applicable to the high-level thread management APIs covered later.
你应该使用哪些成语?第一个使用Runnable对象的习惯用法更为通用,因为Runnable对象可以继承Thread以外的类。第二个习惯用法在简单的应用程序中更容易使用,但受限于你的任务类必须是Thread的后代这一事实。本课重点介绍第一种方法,该方法将Runnable任务与执行任务的Thread对象分开。这种方法不仅更灵活,而且适用于后面介绍的高级线程管理API。
In other words, implementing Runnable
will work in scenarios where your class extends a class other than Thread
. Java does not support multiple inheritance. Also, extending Thread
will not be possible when using some of the high-level thread management APIs. The only scenario where extending Thread
is preferable is in a small application that won't be subject to updates in future. It is almost always better to implement Runnable
as it is more flexible as your project grows. A design change won't have a major impact as you can implement many interfaces in java, but only extend one class.
换句话说,实现Runnable将在您的类扩展Thread以外的类的情况下工作。 Java不支持多重继承。此外,使用某些高级线程管理API时,无法扩展Thread。扩展线程的唯一方案是在一个小应用程序中,将来不会更新。实现Runnable几乎总是更好,因为随着项目的增长它更灵活。设计更改不会产生重大影响,因为您可以在java中实现许多接口,但只扩展一个类。
#18
6
If I am not wrong, it's more or less similar to
如果我没有错,它或多或少类似于
What is the difference between an interface and abstract class?
接口和抽象类之间有什么区别?
extends establishes "Is A" relation & interface provides "Has a" capability.
extends建立“Is A”关系和接口提供“Has a”能力。
Prefer implements Runnable :
首选实现Runnable:
- If you don't have to extend Thread class and modify Thread API default implementation
- If you are executing a fire and forget command
- If You are already extending another class
如果您不必扩展Thread类并修改Thread API的默认实现
如果您正在执行fire and forget命令
如果您已经扩展了另一个类
Prefer "extends Thread" :
首选“扩展线程”:
- If you have to override any of these Thread methods as listed in oracle documentation page
如果必须覆盖oracle文档页面中列出的任何这些Thread方法
Generally you don't need to override Thread behaviour. So implements Runnable is preferred for most of the times.
通常,您不需要重写Thread行为。因此,大多数情况下,实现Runnable是首选。
On a different note, using advanced ExecutorService
or ThreadPoolExecutorService
API provides more flexibility and control.
另外,使用高级ExecutorService或ThreadPoolExecutorService API可提供更多灵活性和控制。
Have a look at this SE Question:
看看这个SE问题:
ExecutorService vs Casual Thread Spawner
ExecutorService与Casual Thread Spawner
#20
5
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通常在引用和执行可运行代码的方式方面提供更大的灵活性。
#21
5
One reason you'd want to implement an interface rather than extend a base class is that you are already extending some other class. You can only extend one class, but you can implement any number of interfaces.
您希望实现接口而不是扩展基类的一个原因是您已经扩展了其他类。您只能扩展一个类,但可以实现任意数量的接口。
If you extend Thread, you're basically preventing your logic to be executed by any other thread than 'this'. If you only want some thread to execute your logic, it's better to just implement Runnable.
如果你扩展Thread,你基本上会阻止你的逻辑被“this”之外的任何其他线程执行。如果您只想要一些线程来执行您的逻辑,那么最好只实现Runnable。
#22
5
if you use runnable you can save the space to extend to any of your other class.
如果使用runnable,则可以节省空间以扩展到任何其他类。
#23
5
Can we re-visit the basic reason we wanted our class to behave as a Thread
?There is no reason at all, we just wanted to execute a task, most likely in an asynchronous mode, which precisely means that the execution of the task must branch from our main thread and the main thread if finishes early, may or may not wait for the branched path(task).
我们可以重新访问我们希望我们的类作为线程运行的基本原因吗?没有任何理由,我们只是想执行一个任务,很可能是在异步模式下,这恰恰意味着任务的执行必须从我们的主线程和主线程分支如果提前完成,可能会或可能不会等待分支路径(任务)。
If this is the whole purpose, then where do I see the need of a specialized Thread. This can be accomplished by picking up a RAW Thread from the System's Thread Pool and assigning it our task (may be an instance of our class) and that is it.
如果这是整个目的,那么我在哪里可以看到需要专门的线程。这可以通过从系统的线程池中获取RAW线程并为其分配我们的任务(可能是我们类的一个实例)来实现,就是这样。
So let us obey the OOPs concept and write a class of the type we need. There are many ways to do things, doing it in the right way matters.
因此,让我们遵守OOP概念并编写一个我们需要的类。有很多方法可以做到,以正确的方式做事很重要。
We need a task, so write a task definition which can be run on a Thread. So use Runnable.
我们需要一个任务,所以编写一个可以在Thread上运行的任务定义。所以使用Runnable。
Always remember implements
is specially used to impart a behaviour and extends
is used to impart a feature/property.
始终记住工具专门用于传授行为,而延伸则用于传授特征/属性。
We do not want the thread's property, instead we want our class to behave as a task which can be run.
我们不想要线程的属性,而是希望我们的类可以作为可以运行的任务来运行。
#24
4
Yes,If you call ThreadA call , then not need to call the start method and run method is call after call the ThreadA class only.But If use the ThreadB call then need to necessary the start thread for call run method.If you have any more help, reply me.
是的,如果你调用ThreadA调用,那么不需要调用start方法并且调用后只运行方法调用ThreadA类。但是如果使用ThreadB调用则需要启动线程来调用run方法。如果你有任何调用更多帮助,回复我。
#25
4
I find it is most useful to use Runnable for all the reasons mentioned, but sometimes I like to extend Thread so I can create my own thread stopping method and call it directly on the thread I have created.
我发现使用Runnable最有用的原因是所有的原因,但有时我喜欢扩展Thread,所以我可以创建自己的线程停止方法并直接在我创建的线程上调用它。
#26
4
Java does not support multiple inheritence so if you extends Thread class then no other class will be extended.
Java不支持多重继承,因此如果扩展Thread类,则不会扩展其他类。
For Example: If you create an applet then it must extends Applet class so here the only way to create thread is by implementing Runnable interface
例如:如果你创建一个applet然后它必须扩展Applet类,所以这里创建线程的唯一方法是通过实现Runnable接口
#27
4
That's the S of SOLID: Single responsibility.
这是SOLID的S:单一责任。
A thread embodies the running context (as in execution context: stack frame, thread id, etc.) of the asynchronous execution of a piece of code. That piece of code ideally should be the same implementation, whether synchronous or asynchronous.
线程体现了一段代码的异步执行的运行上下文(如执行上下文:堆栈帧,线程ID等)。理想情况下,这段代码应该是相同的实现,无论是同步还是异步。
If you bundle them together in one implementation, you give the resulting object two unrelated causes of change:
如果在一个实现中将它们捆绑在一起,则会为结果对象提供两个不相关的更改原因:
- thread handling in your application (ie. querying and modifying the execution context)
- algorithm implemented by the piece of code (the runnable part)
应用程序中的线程处理(即查询和修改执行上下文)
由一段代码实现的算法(可运行部分)
If the language you use supports partial classes or multiple inheritance, then you can segregate each cause in its own super class, but it boils down to the same as composing the two objects, since their feature sets don't overlap. That's for the theory.
如果您使用的语言支持部分类或多重继承,那么您可以在其自己的超类中隔离每个原因,但它归结为与组合这两个对象相同,因为它们的功能集不重叠。那就是理论。
In practice, generally speaking, a programme does not need to carry more complexity than necessary. If you have one thread working on a specific task, without ever changing that task, there is probably no point in making the tasks separate classes, and your code remains simpler.
实际上,一般来说,程序不需要承担比必要更复杂的程序。如果您有一个线程处理特定任务,而没有更改该任务,则可能没有必要将任务分开,并且您的代码仍然更简单。
In the context of Java, since the facility is already there, it is probably easier to start directly with stand alone Runnable
classes, and pass their instances to Thread
(or Executor
) instances. Once used to that pattern, it is not harder to use (or even read) than the simple runnable thread case.
在Java的上下文中,由于该工具已经存在,因此可能更容易直接使用独立的Runnable类启动,并将其实例传递给Thread(或Executor)实例。一旦习惯了这种模式,它就不会比简单的可运行线程情况更难使用(甚至读取)。
#28
4
Difference between Thread and runnable.If we are creating Thread using Thread class then Number of thread equal to number of object we created .If we are creating thread by implementing the runnable interface then we can use single object for creating multiple thread.So single object is shared by multiple Thread.So it will take less memory
Thread和runnable之间的区别。如果我们使用Thread类创建Thread,那么线程数等于我们创建的对象数。如果我们通过实现runnable接口创建线程,那么我们可以使用单个对象来创建多个thread.So单个对象由多个Thread共享。因此它将占用更少的内存
So depending upon the requirement if our data is not senstive. So It can be shared between multiple Thread we can used Runnable interface.
因此,如果我们的数据不敏感,则取决于要求。所以它可以在多个Thread之间共享,我们可以使用Runnable接口。
#29
4
Adding my two cents here -Always whenever possible use implements Runnable
. Below are two caveats on why you should not use extends Thread
s
在这里添加我的两分钱 - 无论何时可能使用实现Runnable。以下是关于为什么不应该使用extends Threads的两个警告
-
Ideally you should never extend the Thread class; the
Thread
class should be madefinal
.At least its methods likethread.getId()
. See this discussion for a bug related to extendingThread
s.理想情况下,您永远不应该扩展Thread类; Thread类应该是final。至少它的方法如thread.getId()。有关扩展线程的错误,请参阅此讨论。
-
Those who like to solve puzzles can see another side effect of extending Thread. The below code will print unreachable code when nobody is notifying them.
那些喜欢解决难题的人可以看到扩展Thread的另一个副作用。当没有人通知他们时,下面的代码将打印无法访问的代码。
Please see http://pastebin.com/BjKNNs2G.
请参阅http://pastebin.com/BjKNNs2G。
public class WaitPuzzle { public static void main(String[] args) throws InterruptedException { DoNothing doNothing = new DoNothing(); new WaitForever(doNothing).start(); new WaitForever(doNothing).start(); new WaitForever(doNothing).start(); Thread.sleep(100); doNothing.start(); while(true) { Thread.sleep(10); } } static class WaitForever extends Thread { private DoNothing doNothing; public WaitForever(DoNothing doNothing) { this.doNothing = doNothing; } @Override public void run() { synchronized (doNothing) { try { doNothing.wait(); // will wait forever here as nobody notifies here } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Unreachable Code"); } } } static class DoNothing extends Thread { @Override public void run() { System.out.println("Do Nothing "); } } }
#30
4
One difference between implementing Runnable and extending Thread is that by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.
实现Runnable和扩展Thread之间的一个区别是,通过扩展Thread,每个线程都有一个与之关联的唯一对象,而实现Runnable,许多线程可以共享同一个对象实例。
A class that implements Runnable is not a thread and just a class. For a Runnable to be executed by a Thread, you need to create an instance of Thread and pass the Runnable instance in as the target.
实现Runnable的类不是一个线程而只是一个类。对于由Thread执行的Runnable,您需要创建Thread的实例并将Runnable实例作为目标传递。
In most cases, the Runnable interface should be used if you are only planning to override the run() method and no other Thread methods. This is important because classes should not be subclassed unless the programmer intends on modifying or enhancing the fundamental behavior of the class.
在大多数情况下,如果您只计划覆盖run()方法而不使用其他Thread方法,则应使用Runnable接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应对类进行子类化。
When there is a need to extend a superclass, implementing the Runnable interface is more appropriate than using the Thread class. Because we can extend another class while implementing Runnable interface to make a thread. But if we just extend the Thread class we can't inherit from any other class.
当需要扩展超类时,实现Runnable接口比使用Thread类更合适。因为我们可以在实现Runnable接口的同时扩展另一个类来创建一个线程。但是如果我们只是扩展Thread类,我们就不能从任何其他类继承。
#1
1477
Yes: implements Runnable
is 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 composition is the philosophically "purer" way to go.
是的:实现Runnable是首选方法,IMO。你并不是真正专注于线程的行为。你只是给它一些东西来运行。这意味着构图是哲学上“更纯粹”的方式。
In practical terms, it means you can implement Runnable
and extend from another class as well.
实际上,它意味着您可以实现Runnable并从另一个类扩展。
#2
502
tl;dr: implements Runnable is better. However, the caveat is important
tl; dr:实现Runnable更好。但是,警告很重要
In general, I would recommend using something like Runnable
rather than Thread
because it allows you to keep your work only loosely coupled with your choice of concurrency. For example, if you use a Runnable
and decide later on that this doesn't in fact require it's own Thread
, you can just call threadA.run().
一般来说,我建议使用像Runnable而不是Thread这样的东西,因为它允许你保持你的工作只与你选择的并发性松散耦合。例如,如果你使用Runnable并稍后决定这实际上不需要它自己的Thread,你可以调用threadA.run()。
Caveat: Around here, I strongly discourage the use of raw Threads. I much prefer the use of Callables and 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.
警告:在这里,我强烈反对使用原始线程。我更喜欢使用Callables和FutureTasks(来自javadoc:“可取消的异步计算”)。超时,正确取消和现代并发支持的线程池的集成对我来说比成堆的原始线程更有用。
Follow-up: there is a FutureTask
constructor that 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 runnable
with your threadA
, we get the following:
因此,如果我们用threadA替换他们的runnable,我们得到以下内容:
new FutureTask<Object>(threadA, null)
Another option that allows you to stay closer to Runnables is a ThreadPoolExecutor. You can use the execute method 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());
#3
233
Moral of the story:
故事的道德启示:
Inherit only if you want to override some behavior.
仅在您要覆盖某些行为时继承。
Or rather it should be read as:
或者更确切地说,它应该被理解为:
Inherit less, interface more.
继承少,界面更多。
#4
190
Well so many good Answers, i want to add more on this. This will help to understand Extending v/s Implementing Thread
.
Extends binds two class files very closely and can cause some pretty hard to deal with code.
那么多好的答案,我想在此添加更多。这将有助于理解扩展v / s实现线程。 Extends非常紧密地绑定两个类文件,并且可能导致一些非常难以处理的代码。
Both approaches do the same job but there have been some differences.
The most common difference is
两种方法都做同样的工作,但存在一些差异。最常见的区别是
- When you extends Thread class, after that you can’t extend any other class which you required. (As you know, Java does not allow inheriting more than one class).
- When you implements Runnable, you can save a space for your class to extend any other class in future or now.
当您扩展Thread类时,之后您无法扩展您需要的任何其他类。 (如您所知,Java不允许继承多个类)。
实现Runnable时,可以为类保存一个空间,以便将来或现在扩展任何其他类。
However, one significant difference between implementing Runnable and extending Thread is that
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.
但是,实现Runnable和扩展Thread之间的一个显着区别是,通过扩展Thread,每个线程都有一个与之关联的唯一对象,而实现Runnable时,许多线程可以共享同一个对象实例。
The following example helps you to understand more clearly
以下示例可帮助您更清楚地理解
//Implement Runnable Interface... class ImplementsRunnable implements Runnable {private int counter = 0;public void run() { counter++; System.out.println("ImplementsRunnable : Counter : " + counter); }}//Extend Thread class...class ExtendsThread extends Thread {private int counter = 0;public void run() { counter++; System.out.println("ExtendsThread : Counter : " + counter); }}//Use above classes here in main to understand the differences more clearly...public class ThreadVsRunnable {public static void main(String args[]) throws Exception { // Multiple threads share the same object. ImplementsRunnable rc = new ImplementsRunnable(); Thread t1 = new Thread(rc); t1.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread Thread t2 = new Thread(rc); t2.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread Thread t3 = new Thread(rc); t3.start(); // Creating new instance for every thread access. ExtendsThread tc1 = new ExtendsThread(); tc1.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread ExtendsThread tc2 = new ExtendsThread(); tc2.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread ExtendsThread tc3 = new ExtendsThread(); tc3.start(); }}
Output of the above program.
输出上述程序。
ImplementsRunnable : Counter : 1ImplementsRunnable : Counter : 2ImplementsRunnable : Counter : 3ExtendsThread : Counter : 1ExtendsThread : Counter : 1ExtendsThread : Counter : 1
In the Runnable interface approach, only one instance of a class is being created and it has been shared by different threads. So the value of counter is incremented for each and every thread access.
在Runnable接口方法中,只创建了一个类的一个实例,并且它已由不同的线程共享。因此,对于每个线程访问,计数器的值都会递增。
Whereas, Thread class approach, you must have to create separate instance for every thread access. Hence different memory is allocated for every class instances and each has separate counter, the value remains same, which means no increment will happen because none of the object reference is same.
而Thread类方法必须为每个线程访问创建单独的实例。因此,为每个类实例分配不同的内存,每个内存都有单独的计数器,值保持相同,这意味着不会发生任何增量,因为没有任何对象引用是相同的。
When to use Runnable?
Use Runnable interface when you want to access the same resource from the group of threads. Avoid using Thread class here, because multiple objects creation consumes more memory and it becomes a big performance overhead.
什么时候使用Runnable?如果要从线程组访问相同的资源,请使用Runnable接口。避免在这里使用Thread类,因为多个对象创建会占用更多内存,并且会成为很大的性能开销。
A class that implements Runnable is not a thread and just a class. For a Runnable to become a Thread, You need to create an instance of Thread and passing itself in as the target.
实现Runnable的类不是一个线程而只是一个类。要使Runnable成为线程,您需要创建一个Thread实例并将其自身作为目标传递。
In most cases, the Runnable interface should be used if you are only planning to override the run()
method and no other Thread methods. This is important because classes should not be subclassed unless the programmer intends on modifying or enhancing the fundamental behavior of the class.
在大多数情况下,如果您只计划覆盖run()方法而不使用其他Thread方法,则应使用Runnable接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应对类进行子类化。
When there is a need to extend a superclass, implementing the Runnable interface is more appropriate than using the Thread class. Because we can extend another class while implementing Runnable interface to make a thread.
当需要扩展超类时,实现Runnable接口比使用Thread类更合适。因为我们可以在实现Runnable接口的同时扩展另一个类来创建一个线程。
I hope this will help!
我希望这个能帮上忙!
#5
73
One thing that I'm surprised hasn't been mentioned yet is that implementing Runnable
makes 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 Runnable
it 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 Runnable
than if you bind yourself to Thread
.
如果你扩展线程,那么你正在做的动作总是在一个线程中。但是,如果您实现Runnable,则不必如此。您可以在一个线程中运行它,或者将它传递给某种执行器服务,或者只是作为单个线程应用程序中的任务传递它(可能在以后运行,但在同一个线程内)。如果你只使用Runnable,那么这些选项会比将你自己绑定到Thread更加开放。
#6
66
If you want to implements or extends any other class then Runnable
interface is most preferable other wise if you do not want any other class to extend or implement then Thread
class is preferable
如果你想实现或扩展任何其他类,那么如果你不希望任何其他类扩展或实现那么Runnable接口是最优选的,那么Thread类是更可取的
The most common difference is
最常见的区别是
When you extends Thread
class, after that you can’t extend any other class which you required. (As you know, Java does not allow inheriting more than one class).
当您扩展Thread类时,之后您无法扩展您需要的任何其他类。 (如您所知,Java不允许继承多个类)。
When you implements Runnable
, you can save a space for your class to extend any other class in future or now.
实现Runnable时,可以为类保存一个空间,以便将来或现在扩展任何其他类。
-
Java doesn't support multiple inheritance, which means you can only extend one class in Java so once you extended Thread class you lost your chance and can not extend or inherit another class in Java.
Java不支持多重继承,这意味着你只能在Java中扩展一个类,所以一旦你扩展了Thread类,你就失去了机会,无法在Java中扩展或继承另一个类。
-
In Object oriented programming extending a class generally means adding new functionality, modifying or improving behaviors. If we are not making any modification on Thread then use Runnable interface instead.
在面向对象的编程中,扩展类通常意味着添加新功能,修改或改进行为。如果我们不在Thread上进行任何修改,那么请改用Runnable接口。
-
Runnable interface represent a Task which can be executed by either plain Thread or Executors or any other means. so logical separation of Task as Runnable than Thread is good design decision.
Runnable接口表示一个Task,它可以由普通的Thread或Executor或任何其他方法执行。所以将Task作为Runnable与Thread进行逻辑分离是一个很好的设计决策。
-
Separating task as Runnable means we can reuse the task and also has liberty to execute it from different means. since you can not restart a Thread once it completes. again Runnable vs Thread for task, Runnable is winner.
将任务分离为Runnable意味着我们可以重用该任务,并且可以*地从不同的方式执行它。因为一旦完成就无法重启线程。再次Runnable vs Thread for task,Runnable是胜利者。
-
Java designer recognizes this and that's why Executors accept Runnable as Task and they have worker thread which executes those task.
Java设计者认识到这一点,这就是Executors接受Runnable作为Task的原因,他们有工作线程来执行这些任务。
-
Inheriting all Thread methods are additional overhead just for representing a Task which can be done easily with Runnable.
继承所有Thread方法只是用于表示可以使用Runnable轻松完成的Task的额外开销。
Courtesy from javarevisited.blogspot.com
礼貌来自javarevisited.blogspot.com
These were some of notable difference between Thread and Runnable in Java, if you know any other differences on Thread vs Runnable than please share it via comments. I personally use Runnable over Thread for this scenario and recommends to use Runnable or Callable interface based on your requirement.
这些是Java中Thread和Runnable之间的一些显着差异,如果你知道Thread vs Runnable上的任何其他差异,请通过评论分享。我个人在这种情况下使用Runnable over Thread,并建议根据您的要求使用Runnable或Callable接口。
However, the significant difference is.
但是,显着的区别是。
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.
当你扩展Thread类时,你的每个线程都会创建唯一的对象并与之关联。当你实现Runnable时,它会将同一个对象共享给多个线程。
#7
61
Actually, It is not wise to compare Runnable
and Thread
with each other.
实际上,将Runnable和Thread相互比较是不明智的。
This two have a dependency and relationship in multi-threading just like Wheel and Engine
relationship of motor vehicle.
这两者在多线程中具有依赖性和关系,就像机动车的车轮和发动机关系一样。
I would say, there is only one way for multi-threading with two steps. Let me make my point.
我想说,只有一种方法可以通过两个步骤实现多线程。让我说明我的观点。
Runnable:
When implementing interface Runnable
it means you are creating something which is run able
in a different thread. Now creating something which can run inside a thread (runnable inside a thread), doesn't mean to creating a Thread.
So the class MyRunnable
is nothing but a ordinary class with a void run
method.And it's objects will be some ordinary objects with only a method run
which will execute normally when called. (unless we pass the object in a thread).
Runnable:当实现接口Runnable时,它意味着你正在创建一个可以在不同线程中运行的东西。现在创建可以在线程内运行的东西(在线程内可运行)并不意味着创建一个Thread。所以类MyRunnable只不过是一个带有void run方法的普通类。它的对象将是一些普通的对象,只有一个方法运行,在调用时会正常执行。 (除非我们在一个线程中传递对象)。
Thread:class Thread
, I would say A very special class with the capability of starting a new Thread which actually enables multi-threading through its start()
method.
Thread:class Thread,我想说一个非常特殊的类,它具有启动一个新Thread的能力,它实际上通过start()方法实现了多线程。
Why not wise to compare?
Because we need both of them for multi-threading.
为什么不明智地比较?因为我们需要它们用于多线程。
For Multi-threading we need two things:
对于多线程,我们需要两件事:
- Something that can run inside a Thread (Runnable).
- Something That can start a new Thread (Thread).
可以在Thread(Runnable)中运行的东西。
可以启动新线程(线程)的东西。
So technically and theoretically both of them is necessary to start a thread, one will run and one will make it run (Like Wheel and Engine
of motor vehicle).
因此从技术上和理论上讲,它们都是启动螺纹所必需的,一个将运行,一个将使其运行(如机动车的车轮和发动机)。
That's why you can not start a thread with MyRunnable
you need to pass it to a instance of Thread
.
这就是为什么你不能用MyRunnable启动一个线程,你需要将它传递给一个Thread实例。
But it is possible to create and run a thread only using class Thread
because Class Thread
implements Runnable
so we all know Thread
also is a Runnable
inside.
但是有可能只使用类Thread来创建和运行一个线程,因为Class Thread实现了Runnable,所以我们都知道Thread也是一个Runnable。
Finally Thread
and Runnable
are complement to each other for multithreading not competitor or replacement.
最后,Thread和Runnable是多线程而不是竞争对手或替代者的补充。
#8
41
You should implement Runnable, but if you are running on Java 5 or higher, you should not start it with new Thread
but use an ExecutorService instead. For details see: How to implement simple threading in Java.
您应该实现Runnable,但是如果您在Java 5或更高版本上运行,则不应该使用新的Thread启动它,而是使用ExecutorService。有关详细信息,请参阅:如何在Java中实现简单线程。
#9
31
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实例,所以这是错误的。
#10
19
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那样实现一个非常模糊的界面。
#11
16
With the release of Java 8, there is now a third option.
随着Java 8的发布,现在有第三种选择。
Runnable
is a functional interface, which means that instances of it can be created with lambda expressions or method references.
Runnable是一个功能接口,这意味着可以使用lambda表达式或方法引用创建它的实例。
Your example can be replaced with:
您的示例可以替换为:
new Thread(() -> { /* Code here */ }).start()
or if you want to use an ExecutorService
and a method reference:
或者如果要使用ExecutorService和方法引用:
executor.execute(runner::run)
These are not only much shorter than your examples, but also come with many of the advantages stated in other answers of using Runnable
over Thread
, such as single responsibility and using composition because you're not specializing the thread's behaviour. This way also avoids creating an extra class if all you need is a Runnable
as you do in your examples.
这些不仅比您的示例短得多,而且还具有使用Runnable over Thread的其他答案中陈述的许多优点,例如单一责任和使用组合,因为您没有专门化线程的行为。如果你需要的只是一个Runnable,就像在你的例子中一样,这种方式也避免了创建一个额外的类。
#12
15
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。
#13
12
- Java doesn't support multiple inheritance, which means you can only extend one class in Java so once you extended
Thread
class you lost your chance and can not extend or inherit another class in Java. - In object-oriented programming extending a class generally means adding new functionality, modifying or improving behaviors. If we are not making any modification on
Thread
than useRunnable
interface instead. -
Runnable
interface represent aTask
which can be executed by either plainThread
orExecutors
or any other means. So logical separation ofTask
asRunnable
thanThread
is good design decision. - Separating task as
Runnable
means we can reuse the task and also has liberty to execute it from different means. Since you can not restart aThread
once it completes, againRunnable
vsThread
for task,Runnable
is winner. - Java designer recognizes this and that's why
Executors
acceptRunnable
asTask
and they have worker thread which executes those task. - Inheriting all
Thread
methods are additional overhead just for representing aTask
which can can be done easily withRunnable
.
Java不支持多重继承,这意味着你只能在Java中扩展一个类,所以一旦你扩展了Thread类,你就失去了机会,无法在Java中扩展或继承另一个类。
在面向对象的编程中,扩展类通常意味着添加新功能,修改或改进行为。如果我们不在Thread上进行任何修改而不是使用Runnable接口。
Runnable接口表示一个Task,它可以由普通的Thread或Executor或任何其他方法执行。因此,将Task作为Runnable与Thread进行逻辑分离是一个很好的设计决策。
将任务分离为Runnable意味着我们可以重用该任务,并且可以*地从不同的方式执行它。由于一旦完成就无法重新启动线程,再次运行Runnable vs Thread任务,Runnable就是胜利者。
Java设计者认识到这一点,这就是Executors接受Runnable作为Task的原因,他们有工作线程来执行这些任务。
继承所有Thread方法只是用于表示可以使用Runnable轻松完成的Task的额外开销。
#14
10
Runnable because:
- Leaves more flexibility for theRunnable implementation to extendanother class
- Separates the code fromexecution
- Allows you to run yourrunnable from a Thread Pool, theevent thread, or in any other way inthe future.
为theRunnable实现提供了更大的灵活性,以扩展其他类
分离代码fromexecution
允许您从线程池,事件线程或以后以任何其他方式运行您的运行。
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是一个更好的解决方案。
#15
10
Everyone here seems to think that implementing Runnable is the way to go and I don't really disagree with them but there is also a case for extending Thread in my opinion, in fact you have sort of demonstrated it in your code.
这里的每个人似乎认为实现Runnable是要走的路,我并不是真的不同意它们,但在我看来还有一个扩展Thread的案例,事实上你已经在你的代码中展示了它。
If you implement Runnable then the class that implements Runnable has no control over the thread name, it is the calling code that can set the thread name, like so:
如果实现Runnable,那么实现Runnable的类无法控制线程名称,它是可以设置线程名称的调用代码,如下所示:
new Thread(myRunnable,"WhateverNameiFeelLike");
but if you extend Thread then you get to manage this within the class itself (just like in your example you name the thread 'ThreadB'). In this case you:
但是如果你扩展Thread然后你就可以在类本身内管理它(就像在你的例子中你命名线程'ThreadB')。在这种情况下你:
A) might give it a more useful name for debugging purposes
A)可能会为调试目的提供一个更有用的名称
B) are forcing that that name be used for all instances of that class (unless you ignore the fact that it is a thread and do the above with it as if it is a Runnable but we are talking about convention here in any case so can ignore that possibility I feel).
B)强制该名称用于该类的所有实例(除非你忽略它是一个线程并使用它执行上面的操作,就好像它是一个Runnable但我们在这里谈论约定,所以可以忽略我觉得的那种可能性)。
You might even for example take a stack trace of its creation and use that as the thread name. This might seem odd but depending on how your code is structured it can be very useful for debugging purposes.
您甚至可以例如获取其创建的堆栈跟踪并将其用作线程名称。这可能看起来很奇怪,但根据代码的结构,它对调试非常有用。
This might seem like a small thing but where you have a very complex application with a lot of threads and all of a sudden things 'have stopped' (either for reasons of deadlock or possibly because of a flaw in a network protocol which would be less obvious - or other endless reasons) then getting a stack dump from Java where all the threads are called 'Thread-1','Thread-2','Thread-3' is not always very useful (it depends on how your threads are structured and whether you can usefully tell which is which just by their stack trace - not always possible if you are using groups of multiple threads all running the same code).
这可能看起来像一个小东西,但你有一个非常复杂的应用程序,有很多线程,突然之间“已经停止”(出于死锁的原因,或者可能是因为网络协议中的缺陷会少一些显然 - 或其他无限的原因)然后从Java获得堆栈转储,其中所有线程被称为'Thread-1','Thread-2','Thread-3'并不总是非常有用(它取决于你的线程如何结构化以及是否可以通过堆栈跟踪有用地告诉哪个是哪个 - 如果您使用的是多个线程的组都运行相同的代码,则不总是可行的。
Having said that you could of course also do the above in a generic way by creating an extension of the thread class which sets its name to a stack trace of its creation call and then use that with your Runnable implementations instead of the standard java Thread class (see below) but in addition to the stack trace there might be more context specific information that would be useful in the thread name for debugging (a reference to one of many queues or sockets it could processing for example in which case you might prefer to extend Thread specifically for that case so that you can have the compiler force you (or others using your libraries) to pass in certain info (e.g. the queue/socket in question) for use in the name).
说过你当然也可以通过创建一个线程类的扩展来以一般方式完成上述操作,该线程类将其名称设置为其创建调用的堆栈跟踪,然后将其与Runnable实现而不是标准java Thread类一起使用(参见下文)但除了堆栈跟踪之外,可能还有更多特定于上下文的信息,这些信息在调试的线程名称中很有用(对可以处理的许多队列或套接字之一的引用,例如在这种情况下您可能更喜欢特别针对该情况扩展Thread,以便您可以让编译器强制您(或其他使用您的库)传递某些信息(例如,有问题的队列/套接字)以便在名称中使用)。
Here's an example of the generic thread with the calling stack trace as its name:
以下是调用堆栈跟踪作为其名称的通用线程的示例:
public class DebuggableThread extends Thread { private static String getStackTrace(String name) { Throwable t= new Throwable("DebuggableThread-"+name); ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(os); t.printStackTrace(ps); return os.toString(); } public DebuggableThread(String name) { super(getStackTrace(name)); } public static void main(String[] args) throws Exception { System.out.println(new Thread()); System.out.println(new DebuggableThread("MainTest")); }}
and here's a sample of the output comparing the two names:
这是一个比较两个名称的输出样本:
Thread[Thread-1,5,main]Thread[java.lang.Throwable: DebuggableThread-MainTest at DebuggableThread.getStackTrace(DebuggableThread.java:6) at DebuggableThread.<init>(DebuggableThread.java:14) at DebuggableThread.main(DebuggableThread.java:19),5,main]
#16
10
Since this is a very popular topic and the good answers are spread all over and dealt with in great depth, I felt it is justifiable to compile the good answers from the others into a more concise form, so newcomers have an easy overview upfront:
由于这是一个非常受欢迎的话题,而且好的答案遍布各处并深入处理,我觉得将其他人的好答案汇编成更简洁的形式是合理的,因此新人有一个简单的概述:
-
You usually extend a class to add or modify functionality. So, if you don't want to overwrite any Thread behavior, then use Runnable.
您通常会扩展一个类来添加或修改功能。因此,如果您不想覆盖任何Thread行为,请使用Runnable。
-
In the same light, if you don't need to inherit thread methods, you can do without that overhead by using Runnable.
同样,如果您不需要继承线程方法,那么使用Runnable可以避免这种开销。
-
Single inheritance: If you extend Thread you cannot extend from any other class, so if that is what you need to do, you have to use Runnable.
单继承:如果扩展Thread,则无法从任何其他类扩展,因此如果您需要这样做,则必须使用Runnable。
-
It is good design to separate domain logic from technical means, in that sense it is better to have a Runnable task isolating your task from your runner.
将域逻辑与技术手段分开是一种很好的设计,从这个意义上说,让Runnable任务将你的任务与你的跑步者隔离开来是更好的选择。
-
You can execute the same Runnable object multiple times, a Thread object, however, can only be started once. (Maybe the reason, why Executors do accept Runnables, but not Threads.)
您可以多次执行相同的Runnable对象,但是,Thread对象只能启动一次。 (也许是原因,为什么Executors接受Runnables,但不接受Threads。)
-
If you develop your task as Runnable, you have all flexibility how to use it now and in the future. You can have it run concurrently via Executors but also via Thread. And you still could also use/call it non-concurrently within the same thread just as any other ordinary type/object.
如果您将任务开发为Runnable,那么您现在和将来都可以灵活使用它。您可以通过Executors同时运行它,也可以通过Thread运行它。而你仍然可以在同一个线程中非同时使用/调用它,就像任何其他普通类型/对象一样。
-
This makes it also easier to separate task-logic and concurrency aspects in your unit tests.
这使得在单元测试中分离任务逻辑和并发方面也变得更容易。
-
If you are interested in this question, you might be also interested in the difference between Callable and Runnable.
如果您对此问题感兴趣,您可能也对Callable和Runnable之间的区别感兴趣。
#17
8
This is discussed in Oracle's Defining and Starting a Thread tutorial:
这在Oracle的定义和启动线程教程中讨论:
Which of these idioms should you use? The first idiom, which employs a Runnable object, is more general, because the Runnable object can subclass a class other than Thread. The second idiom is easier to use in simple applications, but is limited by the fact that your task class must be a descendant of Thread. This lesson focuses on the first approach, which separates the Runnable task from the Thread object that executes the task. Not only is this approach more flexible, but it is applicable to the high-level thread management APIs covered later.
你应该使用哪些成语?第一个使用Runnable对象的习惯用法更为通用,因为Runnable对象可以继承Thread以外的类。第二个习惯用法在简单的应用程序中更容易使用,但受限于你的任务类必须是Thread的后代这一事实。本课重点介绍第一种方法,该方法将Runnable任务与执行任务的Thread对象分开。这种方法不仅更灵活,而且适用于后面介绍的高级线程管理API。
In other words, implementing Runnable
will work in scenarios where your class extends a class other than Thread
. Java does not support multiple inheritance. Also, extending Thread
will not be possible when using some of the high-level thread management APIs. The only scenario where extending Thread
is preferable is in a small application that won't be subject to updates in future. It is almost always better to implement Runnable
as it is more flexible as your project grows. A design change won't have a major impact as you can implement many interfaces in java, but only extend one class.
换句话说,实现Runnable将在您的类扩展Thread以外的类的情况下工作。 Java不支持多重继承。此外,使用某些高级线程管理API时,无法扩展Thread。扩展线程的唯一方案是在一个小应用程序中,将来不会更新。实现Runnable几乎总是更好,因为随着项目的增长它更灵活。设计更改不会产生重大影响,因为您可以在java中实现许多接口,但只扩展一个类。
#18
6
If I am not wrong, it's more or less similar to
如果我没有错,它或多或少类似于
What is the difference between an interface and abstract class?
接口和抽象类之间有什么区别?
extends establishes "Is A" relation & interface provides "Has a" capability.
extends建立“Is A”关系和接口提供“Has a”能力。
Prefer implements Runnable :
首选实现Runnable:
- If you don't have to extend Thread class and modify Thread API default implementation
- If you are executing a fire and forget command
- If You are already extending another class
如果您不必扩展Thread类并修改Thread API的默认实现
如果您正在执行fire and forget命令
如果您已经扩展了另一个类
Prefer "extends Thread" :
首选“扩展线程”:
- If you have to override any of these Thread methods as listed in oracle documentation page
如果必须覆盖oracle文档页面中列出的任何这些Thread方法
Generally you don't need to override Thread behaviour. So implements Runnable is preferred for most of the times.
通常,您不需要重写Thread行为。因此,大多数情况下,实现Runnable是首选。
On a different note, using advanced ExecutorService
or ThreadPoolExecutorService
API provides more flexibility and control.
另外,使用高级ExecutorService或ThreadPoolExecutorService API可提供更多灵活性和控制。
Have a look at this SE Question:
看看这个SE问题:
ExecutorService vs Casual Thread Spawner
ExecutorService与Casual Thread Spawner
#19
#20
5
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通常在引用和执行可运行代码的方式方面提供更大的灵活性。
#21
5
One reason you'd want to implement an interface rather than extend a base class is that you are already extending some other class. You can only extend one class, but you can implement any number of interfaces.
您希望实现接口而不是扩展基类的一个原因是您已经扩展了其他类。您只能扩展一个类,但可以实现任意数量的接口。
If you extend Thread, you're basically preventing your logic to be executed by any other thread than 'this'. If you only want some thread to execute your logic, it's better to just implement Runnable.
如果你扩展Thread,你基本上会阻止你的逻辑被“this”之外的任何其他线程执行。如果您只想要一些线程来执行您的逻辑,那么最好只实现Runnable。
#22
5
if you use runnable you can save the space to extend to any of your other class.
如果使用runnable,则可以节省空间以扩展到任何其他类。
#23
5
Can we re-visit the basic reason we wanted our class to behave as a Thread
?There is no reason at all, we just wanted to execute a task, most likely in an asynchronous mode, which precisely means that the execution of the task must branch from our main thread and the main thread if finishes early, may or may not wait for the branched path(task).
我们可以重新访问我们希望我们的类作为线程运行的基本原因吗?没有任何理由,我们只是想执行一个任务,很可能是在异步模式下,这恰恰意味着任务的执行必须从我们的主线程和主线程分支如果提前完成,可能会或可能不会等待分支路径(任务)。
If this is the whole purpose, then where do I see the need of a specialized Thread. This can be accomplished by picking up a RAW Thread from the System's Thread Pool and assigning it our task (may be an instance of our class) and that is it.
如果这是整个目的,那么我在哪里可以看到需要专门的线程。这可以通过从系统的线程池中获取RAW线程并为其分配我们的任务(可能是我们类的一个实例)来实现,就是这样。
So let us obey the OOPs concept and write a class of the type we need. There are many ways to do things, doing it in the right way matters.
因此,让我们遵守OOP概念并编写一个我们需要的类。有很多方法可以做到,以正确的方式做事很重要。
We need a task, so write a task definition which can be run on a Thread. So use Runnable.
我们需要一个任务,所以编写一个可以在Thread上运行的任务定义。所以使用Runnable。
Always remember implements
is specially used to impart a behaviour and extends
is used to impart a feature/property.
始终记住工具专门用于传授行为,而延伸则用于传授特征/属性。
We do not want the thread's property, instead we want our class to behave as a task which can be run.
我们不想要线程的属性,而是希望我们的类可以作为可以运行的任务来运行。
#24
4
Yes,If you call ThreadA call , then not need to call the start method and run method is call after call the ThreadA class only.But If use the ThreadB call then need to necessary the start thread for call run method.If you have any more help, reply me.
是的,如果你调用ThreadA调用,那么不需要调用start方法并且调用后只运行方法调用ThreadA类。但是如果使用ThreadB调用则需要启动线程来调用run方法。如果你有任何调用更多帮助,回复我。
#25
4
I find it is most useful to use Runnable for all the reasons mentioned, but sometimes I like to extend Thread so I can create my own thread stopping method and call it directly on the thread I have created.
我发现使用Runnable最有用的原因是所有的原因,但有时我喜欢扩展Thread,所以我可以创建自己的线程停止方法并直接在我创建的线程上调用它。
#26
4
Java does not support multiple inheritence so if you extends Thread class then no other class will be extended.
Java不支持多重继承,因此如果扩展Thread类,则不会扩展其他类。
For Example: If you create an applet then it must extends Applet class so here the only way to create thread is by implementing Runnable interface
例如:如果你创建一个applet然后它必须扩展Applet类,所以这里创建线程的唯一方法是通过实现Runnable接口
#27
4
That's the S of SOLID: Single responsibility.
这是SOLID的S:单一责任。
A thread embodies the running context (as in execution context: stack frame, thread id, etc.) of the asynchronous execution of a piece of code. That piece of code ideally should be the same implementation, whether synchronous or asynchronous.
线程体现了一段代码的异步执行的运行上下文(如执行上下文:堆栈帧,线程ID等)。理想情况下,这段代码应该是相同的实现,无论是同步还是异步。
If you bundle them together in one implementation, you give the resulting object two unrelated causes of change:
如果在一个实现中将它们捆绑在一起,则会为结果对象提供两个不相关的更改原因:
- thread handling in your application (ie. querying and modifying the execution context)
- algorithm implemented by the piece of code (the runnable part)
应用程序中的线程处理(即查询和修改执行上下文)
由一段代码实现的算法(可运行部分)
If the language you use supports partial classes or multiple inheritance, then you can segregate each cause in its own super class, but it boils down to the same as composing the two objects, since their feature sets don't overlap. That's for the theory.
如果您使用的语言支持部分类或多重继承,那么您可以在其自己的超类中隔离每个原因,但它归结为与组合这两个对象相同,因为它们的功能集不重叠。那就是理论。
In practice, generally speaking, a programme does not need to carry more complexity than necessary. If you have one thread working on a specific task, without ever changing that task, there is probably no point in making the tasks separate classes, and your code remains simpler.
实际上,一般来说,程序不需要承担比必要更复杂的程序。如果您有一个线程处理特定任务,而没有更改该任务,则可能没有必要将任务分开,并且您的代码仍然更简单。
In the context of Java, since the facility is already there, it is probably easier to start directly with stand alone Runnable
classes, and pass their instances to Thread
(or Executor
) instances. Once used to that pattern, it is not harder to use (or even read) than the simple runnable thread case.
在Java的上下文中,由于该工具已经存在,因此可能更容易直接使用独立的Runnable类启动,并将其实例传递给Thread(或Executor)实例。一旦习惯了这种模式,它就不会比简单的可运行线程情况更难使用(甚至读取)。
#28
4
Difference between Thread and runnable.If we are creating Thread using Thread class then Number of thread equal to number of object we created .If we are creating thread by implementing the runnable interface then we can use single object for creating multiple thread.So single object is shared by multiple Thread.So it will take less memory
Thread和runnable之间的区别。如果我们使用Thread类创建Thread,那么线程数等于我们创建的对象数。如果我们通过实现runnable接口创建线程,那么我们可以使用单个对象来创建多个thread.So单个对象由多个Thread共享。因此它将占用更少的内存
So depending upon the requirement if our data is not senstive. So It can be shared between multiple Thread we can used Runnable interface.
因此,如果我们的数据不敏感,则取决于要求。所以它可以在多个Thread之间共享,我们可以使用Runnable接口。
#29
4
Adding my two cents here -Always whenever possible use implements Runnable
. Below are two caveats on why you should not use extends Thread
s
在这里添加我的两分钱 - 无论何时可能使用实现Runnable。以下是关于为什么不应该使用extends Threads的两个警告
-
Ideally you should never extend the Thread class; the
Thread
class should be madefinal
.At least its methods likethread.getId()
. See this discussion for a bug related to extendingThread
s.理想情况下,您永远不应该扩展Thread类; Thread类应该是final。至少它的方法如thread.getId()。有关扩展线程的错误,请参阅此讨论。
-
Those who like to solve puzzles can see another side effect of extending Thread. The below code will print unreachable code when nobody is notifying them.
那些喜欢解决难题的人可以看到扩展Thread的另一个副作用。当没有人通知他们时,下面的代码将打印无法访问的代码。
Please see http://pastebin.com/BjKNNs2G.
请参阅http://pastebin.com/BjKNNs2G。
public class WaitPuzzle { public static void main(String[] args) throws InterruptedException { DoNothing doNothing = new DoNothing(); new WaitForever(doNothing).start(); new WaitForever(doNothing).start(); new WaitForever(doNothing).start(); Thread.sleep(100); doNothing.start(); while(true) { Thread.sleep(10); } } static class WaitForever extends Thread { private DoNothing doNothing; public WaitForever(DoNothing doNothing) { this.doNothing = doNothing; } @Override public void run() { synchronized (doNothing) { try { doNothing.wait(); // will wait forever here as nobody notifies here } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Unreachable Code"); } } } static class DoNothing extends Thread { @Override public void run() { System.out.println("Do Nothing "); } } }
#30
4
One difference between implementing Runnable and extending Thread is that by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.
实现Runnable和扩展Thread之间的一个区别是,通过扩展Thread,每个线程都有一个与之关联的唯一对象,而实现Runnable,许多线程可以共享同一个对象实例。
A class that implements Runnable is not a thread and just a class. For a Runnable to be executed by a Thread, you need to create an instance of Thread and pass the Runnable instance in as the target.
实现Runnable的类不是一个线程而只是一个类。对于由Thread执行的Runnable,您需要创建Thread的实例并将Runnable实例作为目标传递。
In most cases, the Runnable interface should be used if you are only planning to override the run() method and no other Thread methods. This is important because classes should not be subclassed unless the programmer intends on modifying or enhancing the fundamental behavior of the class.
在大多数情况下,如果您只计划覆盖run()方法而不使用其他Thread方法,则应使用Runnable接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应对类进行子类化。
When there is a need to extend a superclass, implementing the Runnable interface is more appropriate than using the Thread class. Because we can extend another class while implementing Runnable interface to make a thread. But if we just extend the Thread class we can't inherit from any other class.
当需要扩展超类时,实现Runnable接口比使用Thread类更合适。因为我们可以在实现Runnable接口的同时扩展另一个类来创建一个线程。但是如果我们只是扩展Thread类,我们就不能从任何其他类继承。