Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程与可运行线程_Java_Multithreading - Fatal编程技术网

Java线程与可运行线程

Java线程与可运行线程,java,multithreading,Java,Multithreading,在阅读Thread和Runnable from之间的显著差异时,我遇到了一个差异: 扩展线程类时,每个线程都会创建唯一的对象并与之关联。其中 实现Runnable时,它将同一对象共享给多个线程。 有以下代码: class ImplementsRunnable implements Runnable { private int counter = 0; public void run() { counter++; System.out.println("Implemen

在阅读Thread和Runnable from之间的显著差异时,我遇到了一个差异:

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

实现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
它证明了上面给出的差异。我对下面给出的代码做了一点修改:

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
我理解的事实是,在这里,同一个对象(extendstread)由三个线程共享。但我很困惑,它与实现Runnable有什么不同。在这里,即使*extendstread*扩展了Thread,我们仍然能够将这个类的对象共享给其他线程。在我看来,上述差异没有任何意义


谢谢。

实现Runnable的主要区别在于您不会“消费”您的单一继承。考虑这些类声明:

public class HelloRunnable implements Runnable extends AbstractHello

public class HelloRunnable extends Thread
在继承方面,您可以使用Runnable做更多的工作。

以下是状态

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

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

所以这两种方式

public class MyThread extends Thread {
    // overriden from Runnable, which Thread implements
    public void run() {
        ...
    }
}

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

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

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

 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();
将有自己的副本(这就是实例变量的工作方式)。因此,当您启动每个线程时,每个线程都会增加它自己的字段副本

在第二种情况下,使用
线程
子类作为
线程
构造函数的
可运行
参数。

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);
它与您传递的
extendedsthread
对象相同,因此它的
计数器
字段由所有线程递增。它相当于您以前使用的
ImplementsRunnable

从评论中添加:

首先要了解的是
线程
类实现了
可运行
,因此您可以在任何可以使用
可运行
的地方使用
线程
实例

new Thread(new Thread()); // won't do anything, but just to demonstrate
使用创建
线程时

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

创建自定义线程时,如

new ExtendsThread();

然后启动它,它在自身上调用
run()

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

public class HelloFrame extends JFrame implements Runnable{

  ...

  public void run(){
    //  thread code
  }

  ...
}  

@helderdarocha这是作为解决方案给出的。Rupesh Yadav和zEro之间存在冲突。我只是想知道,上面的区别有什么意义呢?困惑来自你的源头;实现runnable时,可以在线程之间共享对象。但你很少会这么做。你也可以用一个线程来做这件事,因为它无论如何都是可运行的,但那会更奇怪。@Sotirious Delimanolis所以,上面的区别是不相关的???@Balwantchouhan你能澄清一下你指的是哪一个上面的区别吗?@Sotirious Delimanolis当然。也就是说,当您扩展Thread类时,每个线程都会创建唯一的对象并与之关联。当您实现Runnable时,它与多个线程共享同一个对象。@BalwantChauhan首先要了解的是
Thread
类实现了
Runnable
,因此您可以在任何可以使用
Runnable
的地方使用
Thread
实例。当您使用
新线程(someRunnable)
创建
线程
并启动它时,该线程将执行给定的
Runnable
实例的
run()
方法。如果该
Runnable
实例恰好也是
Thread
的实例,那么就这样吧,这不会改变任何事情。当您创建一个自定义线程(如
new extendstread()
并启动它时,它会对自身调用
run()
。@SotiriosDelimanolis我能说,通过将线程引用作为参数传递,它只是将旧实例的值复制到新实例吗?因此,输出为
1,2,3
public class HelloFrame extends JFrame implements Runnable{

  ...

  public void run(){
    //  thread code
  }

  ...
}