Java-Thread Vs Runnable

在阅读Thread和Runnable之间的重大区别时,我遇到了一个不同之处:

当您扩展Thread类时,每个线程都会创建唯一对象并与之关联。 在哪里

实现Runnable时,它将同一对象共享给多个线程。

有代码给:

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(); } } 

输出是这样的:

 ImplementsRunnable : Counter : 1 ImplementsRunnable : Counter : 2 ImplementsRunnable : Counter : 3 ExtendsThread : Counter : 1 ExtendsThread : Counter : 1 ExtendsThread : Counter : 1 

它certificate了上面给出的差异。 我在下面给出的代码中稍作修改:

 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); } } 

现在输出是:

 ImplementsRunnable : Counter : 1 ImplementsRunnable : Counter : 2 ImplementsRunnable : Counter : 3 ExtendsThread : Counter : 1 ExtendsThread : Counter : 2 ExtendsThread : Counter : 3 

我理解这样的事实,这里同一个对象(extendsThread)由三个线程共享。 但我在这里很困惑,它与实现Runnable有何不同。 在这里,即使* ExtendsThread *扩展了Thread,我们仍然可以将此类的对象共享给其他线程。 在我看来,上述差异没有任何意义。

谢谢。

这是javadoc所说的内容

两种方法可以创建新的执行线程。 一种是将类声明为Thread的子类 。 该子类应该重写Thread类的run方法。 然后可以分配和启动子类的实例。 例如,计算大于规定值的素数的线程可以写成如下:

创建线程的另一种方法是声明一个实现Runnable接口的类。 该类然后实现run方法。 然后可以分配类的实例,在创建Thread时作为参数传递,然后启动。 此其他样式中的相同示例如下所示:

所以这两种方式

 public class MyThread extends Thread { // overriden from Runnable, which Thread implements public void run() { ... } } ... MyThread thread = new MyThread(); thread.start(); 

要么

 public class MyRunnable implements Runnable{ public void run() { ... } } ... Thread thread = new Thread(new MyRunnable()); thread.start(); 

您的counter字段是实例字段。

在第一种情况下,这里创建的每个对象

  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(); 

将拥有自己的副本(这就是实例变量的工作原理)。 因此,当您启动每个线程时,每个线程都会增加其自己的字段副本。

在第二种情况下, 您使用Thread子类作为Thread构造函数的Runnable参数。

 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); 

它与您传递的ExtendsThread对象相同,因此其counter字段会被所有线程递增。 它几乎等同于您之前使用的ImplementsRunnable

要从评论中添加:

首先要理解的是Thread类实现了Runnable ,因此您可以在任何可以使用Runnable地方使用Thread实例。 例如,

 new Thread(new Thread()); // won't do anything, but just to demonstrate 

使用时创建Thread

 new Thread(someRunnable); 

并启动它, 该线程调用给定的Runnable实例的run()方法 。 如果Runnable实例恰好也是Thread一个实例,那就这样吧。 这不会改变任何事情。

当你创建一个自定义线程时

 new ExtendsThread(); 

并启动它,它自己调用run()

实现Runnable的主要区别在于您不“消耗”单个inheritance。 考虑这些类声明:

 public class HelloRunnable implements Runnable extends AbstractHello public class HelloRunnable extends Thread 

在inheritance方面,您可以使用Runnable做更多事情。

@BalwantChauhan:Runnable接口的一个常见用法是,我们知道在Java的情况下不可能进行多重inheritance。 现在假设您有一个场景,您希望扩展一个类,并且您还想实现线程。 因此,对于那些情况,如果我们继续使用Thread,那么就无法实现它。 例如:假设(在Java Swing的情况下),如果你想创建一个框架,并且你想要在那个框架类中实现线程,那么就不可能扩展JFrame和Thread类,所以在这种情况下我们扩展了JFrame和实现Runnable。

 public class HelloFrame extends JFrame implements Runnable{ ... public void run(){ // thread code } ... }