Java 线程与 Runnable
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21871073/
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
Java-Thread Vs Runnable
提问by Balwant Kumar Singh
While reading through the significant difference between Thread and Runnable from here, I encountered a difference that is:
从这里阅读 Thread 和 Runnable 之间的显着差异时,我遇到了一个差异:
When you extends Thread class, each of your thread creates unique object and associate with it.where as
当您扩展 Thread 类时,您的每个线程都会创建唯一的对象并与之关联。然而
When you implement Runnable, it shares the same object to multiple threads..
当您实现 Runnable 时,它会将同一个对象共享给多个线程。.
There is code give :
有代码给:
class ImplementsRunnable implements Runnable {
private int counter = 0;
public void run() {
counter++;
System.out.println("ImplementsRunnable : Counter : " + counter);
}
}
class ExtendsThread extends Thread {
private int counter = 0;
public void run() {
counter++;
System.out.println("ExtendsThread : Counter : " + counter);
}
}
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();
}
}
The output is something like this:
输出是这样的:
ImplementsRunnable : Counter : 1
ImplementsRunnable : Counter : 2
ImplementsRunnable : Counter : 3
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
It proves differences given above. I make a slight modification in code given below:
它证明了上面给出的差异。我在下面给出的代码中稍作修改:
class ImplementsRunnable implements Runnable {
private int counter = 0;
public void run() {
counter++;
System.out.println("ImplementsRunnable : Counter : " + counter);
}
}
class ExtendsThread extends Thread {
private int counter = 0;
public void run() {
counter++;
System.out.println("ExtendsThread : Counter : " + counter);
}
}
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();
//Modification done here. Only one object is shered by multiple threads here also.
ExtendsThread extendsThread = new ExtendsThread();
Thread thread11 = new Thread(extendsThread);
thread11.start();
Thread.sleep(1000);
Thread thread12 = new Thread(extendsThread);
thread12.start();
Thread.sleep(1000);
Thread thread13 = new Thread(extendsThread);
thread13.start();
Thread.sleep(1000);
}
}
Now the output is :
现在输出是:
ImplementsRunnable : Counter : 1
ImplementsRunnable : Counter : 2
ImplementsRunnable : Counter : 3
ExtendsThread : Counter : 1
ExtendsThread : Counter : 2
ExtendsThread : Counter : 3
I understand the fact that, here same object (extendsThread) is shared by three threads. But I'm confused here that how it is different from implementing Runnable. Here, even if *ExtendsThread *extends Thread, we are still able to share the object of this class to other threads. In my thinking the above difference does not make any sense.
我理解这样一个事实,这里同一个对象(extendsThread)由三个线程共享。但我在这里很困惑,它与实现 Runnable 有何不同。在这里,即使 * ExtendsThread *extends Thread ,我们仍然可以将这个类的对象共享给其他线程。在我看来,上述差异没有任何意义。
Thanks.
谢谢。
回答by jeremyjjbrown
The principle difference in implementing Runnable is that you do not 'consume' your single inheritance. Consider these Class declarations:
实现 Runnable 的主要区别在于您不“消耗”您的单一继承。考虑这些类声明:
public class HelloRunnable implements Runnable extends AbstractHello
public class HelloRunnable extends Thread
You can do more with Runnable when it comes to inheritance.
在继承方面,您可以使用 Runnable 做更多事情。
回答by Sotirios Delimanolis
Here's what the javadocstates
这是javadoc 的说明
There are two ways to create a new thread of execution.One is to declare a class to be a subclass of Thread. This subclass should override the run method of class Thread. An instance of the subclass can then be allocated and started. For example, a thread that computes primes larger than a stated value could be written as follows:
The other way to create a thread is to declare a class that implements the Runnable interface. That class then implements the run method. An instance of the class can then be allocated, passed as an argument when creating Thread, and started.The same example in this other style looks like the following:
有两种方法可以创建新的执行线程。一种是将 类声明为 Thread 的子类。这个子类应该覆盖类 Thread 的 run 方法。然后可以分配和启动子类的实例。例如,计算大于规定值的素数的线程可以写成如下:
创建线程的另一种方法是声明一个实现 Runnable 接口的类。然后该类实现 run 方法。然后可以分配类的实例,在创建 Thread 时将其作为参数传递并启动。其他样式中的相同示例如下所示:
So the two ways
所以两种方式
public class MyThread extends Thread {
// overriden from Runnable, which Thread implements
public void run() {
...
}
}
...
MyThread thread = new MyThread();
thread.start();
Or
或者
public class MyRunnable implements Runnable{
public void run() {
...
}
}
...
Thread thread = new Thread(new MyRunnable());
thread.start();
Your counter
field is an instance field.
您的counter
字段是一个实例字段。
In your first case, each of the objects created here
在你的第一种情况下,这里创建的每个对象
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();
will have their own copy (that's how instance variables work). So when you start each thread, each one increments its own copy of the field.
将有自己的副本(这就是实例变量的工作方式)。因此,当您启动每个线程时,每个线程都会增加自己的字段副本。
In your second case, you are using your Thread
sub class as a Runnable
argument to the Thread
constructor.
在第二种情况下,您使用Thread
子类作为构造函数的Runnable
参数Thread
。
ExtendsThread extendsThread = new ExtendsThread();
Thread thread11 = new Thread(extendsThread);
thread11.start();
Thread.sleep(1000);
Thread thread12 = new Thread(extendsThread);
thread12.start();
Thread.sleep(1000);
Thread thread13 = new Thread(extendsThread);
thread13.start();
Thread.sleep(1000);
It is the same ExtendsThread
object that you pass, so its counter
field gets incremented by all threads. It's pretty much equivalent to your previous usage of ImplementsRunnable
.
它与ExtendsThread
您传递的对象相同,因此counter
所有线程都会增加其字段。它几乎等同于您之前对ImplementsRunnable
.
To add from the comments:
从评论中添加:
First thing to understand is that the Thread
class implements Runnable
, so you can use a Thread
instance anywhere you can use Runnable
.For example,
首先要了解的是Thread
该类实现了Runnable
,因此您可以在Thread
任何可以使用的地方使用实例Runnable
。例如,
new Thread(new Thread()); // won't do anything, but just to demonstrate
When you create a Thread
with
当你创建一个Thread
与
new Thread(someRunnable);
and start it, the thread calls the given Runnable
instance's run()
method. If that Runnable
instance happens to also be an instance of Thread
, so be it. That doesn't change anything.
并启动它,线程调用给定Runnable
实例的run()
方法。如果该Runnable
实例恰好也是 的实例Thread
,那就这样吧。这不会改变任何事情。
When you create a custom thread like
当您创建一个自定义线程时
new ExtendsThread();
and start it, it calls run()
on itself.
并启动它,它会调用run()
自己。
回答by Suneet Bansal
@BalwantChauhan: One common usage of Runnable interface is that as we know that multiple inheritance is not possible in case of Java. Now suppose you have a scenario where you want extends a class and also you want to implement thread. So for those scenario if we go ahead for Thread then it is not possible to achieve it. For example : Suppose (in case of Java Swing), if you want to create a frame and also in that frame class you want to implement thread, then it is not possible to extends JFrame and Thread class so in that case we extends JFrame and implement Runnable.
@BalwantChauhan:Runnable 接口的一种常见用法是,我们知道在 Java 的情况下不可能进行多重继承。现在假设你有一个场景,你想要扩展一个类,并且你想要实现线程。因此,对于那些场景,如果我们继续使用 Thread,则不可能实现它。例如:假设(在 Java Swing 的情况下),如果你想创建一个框架,并且你想在那个框架类中实现线程,那么就不可能扩展 JFrame 和 Thread 类,所以在这种情况下,我们扩展 JFrame 和实现可运行。
public class HelloFrame extends JFrame implements Runnable{
...
public void run(){
// thread code
}
...
}