Java-Thread Vs Runnable [英] Java-Thread Vs Runnable

查看:92
本文介绍了Java-Thread Vs Runnable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读此处的Thread和Runnable之间的重大差异时,我遇到了以下差异:



当您扩展Thread类时,每个线程都会创建唯一对象并与之关联。其中 p>

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



代码为:

  class ImplementsRunnable实现Runnable {

private int counter = 0;

public void run(){
counter ++;
System.out.println(ImplementsRunnable:Counter:+ counter);
}
}

类ExtendsThread扩展线程{

private int counter = 0;

public void run(){
counter ++;
System.out.println(ExtendsThread:Counter:+ counter);
}
}

公共类ThreadVsRunnable {

public static void main(String args [])throws Exception {
// Multiple线程共享同一个对象。
ImplementsRunnable rc = new ImplementsRunnable();
线程t1 =新线程(rc);
t1.start();
Thread.sleep(1000); //在开始下一个线程之前等待1秒
线程t2 =新线程(rc);
t2.start();
Thread.sleep(1000); //在开始下一个线程之前等待1秒
线程t3 =新线程(rc);
t3.start();

//为每个线程访问创建新实例。
ExtendsThread tc1 = new ExtendsThread();
tc1.start();
Thread.sleep(1000); //在开始下一个线程之前等待1秒
ExtendsThread tc2 = new ExtendsThread();
tc2.start();
Thread.sleep(1000); //在开始下一个线程之前等待1秒
ExtendsThread tc3 = new ExtendsThread();
tc3.start();
}
}

输出如下:

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

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

  class ImplementsRunnable实现Runnable {

private int counter = 0;

public void run(){
counter ++;
System.out.println(ImplementsRunnable:Counter:+ counter);
}
}

类ExtendsThread扩展线程{

private int counter = 0;

public void run(){
counter ++;
System.out.println(ExtendsThread:Counter:+ counter);
}
}

公共类ThreadVsRunnable {

public static void main(String args [])throws Exception {
// Multiple线程共享同一个对象。
ImplementsRunnable rc = new ImplementsRunnable();
线程t1 =新线程(rc);
t1.start();
Thread.sleep(1000); //在开始下一个线程之前等待1秒
线程t2 =新线程(rc);
t2.start();
Thread.sleep(1000); //在开始下一个线程之前等待1秒
线程t3 =新线程(rc);
t3.start();

//在此处完成修改。这里也只有一个对象由多个线程进行剪切。
ExtendsThread extendsThread = new ExtendsThread();
线程thread11 =新线程(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方法。然后可以分配和启动子类
的实例。例如,计算
primes大于规定值的线程可以写成如下:



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

所以两种方式

  public class MyThread扩展Thread {
//覆盖Runnable,Thread实现
public void run(){
...
}
}

...
MyThread thread = new MyThread();
thread.start();

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

您的计数器字段是一个实例字段。



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

  ExtendsThread tc1 = new ExtendsThread(); 
tc1.start();
Thread.sleep(1000); //在开始下一个线程之前等待1秒
ExtendsThread tc2 = new ExtendsThread();
tc2.start();
Thread.sleep(1000); //在开始下一个线程之前等待1秒
ExtendsThread tc3 = new ExtendsThread();
tc3.start();

将拥有自己的副本(这就是实例变量的工作方式)。因此,当您启动每个帖子时,每个帖子都会递增自己的字段副本。



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

  ExtendsThread extendsThread = new ExtendsThread(); 
线程thread11 =新线程(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 对象传递,所以它的计数器字段会被所有线程递增。它几乎相当于您之前使用的 ImplementsRunnable



要从评论中添加:



首先要了解的是 Thread 类实现 Runnable ,所以你可以在任何地方使用 Thread 实例 Runnable 例如,

  new Thread(new Thread()); //将不会做任何事情,只是为了演示

创建 Thread with

  new Thread(someRunnable); 

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



创建自定义线程时

  new ExtendsThread() ; 

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


While reading through the significant difference between Thread and Runnable from here, I encountered a difference that is:

When you extends Thread class, each of your thread creates unique object and associate with it. where as

When you implement Runnable, it shares the same object to multiple threads..

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.

Thanks.

解决方案

Here's what the javadoc states

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:

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.

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.

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.

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,

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

When you create a Thread with

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.

When you create a custom thread like

new ExtendsThread();

and start it, it calls run() on itself.

这篇关于Java-Thread Vs Runnable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆