Java中线程类和可运行接口之间的区别

作者: Laura McKinney
创建日期: 1 四月 2021
更新日期: 14 可能 2024
Anonim
【day18】16 尚硅谷 Java语言高级 线程的常用方法
视频: 【day18】16 尚硅谷 Java语言高级 线程的常用方法

内容


线程可以通过两种方式定义。首先, 扩展Thread类 已经实现了Runnable接口。第二,直接 实现一个Runnable接口。通过扩展Thread类定义线程时,必须重写Thread类中的run()方法。当定义实现Runnable接口的线程时,您必须实现Runnable接口的唯一run()方法。 Thread和Runnable之间的基本区别是,通过扩展Thread类定义的每个线程都会创建一个唯一的对象并与该对象关联。另一方面,通过实现Runnable接口定义的每个线程共享同一对象。

让我们借助下面显示的比较表来观察Thread和Runnable之间的其他差异:

  1. 比较表
  2. 定义
  3. 关键差异
  4. 结论

比较表

比较基础线可运行
基本的每个线程创建一个唯一的对象并与之关联。多个线程共享相同的对象。
记忆 当每个线程创建一个唯一的对象时,需要更多的内存。由于多个线程共享同一对象,因此使用的内存更少。
延伸在Java中,不允许多重继承,因此,在一个类扩展了Thread类之后,便无法扩展任何其他类。如果一个类定义了实现Runnable接口的线程,则它有可能扩展一个类。
采用 用户仅在想要覆盖Thread类中的其他方法时才必须扩展线程类。如果只想专门介绍run方法,那么实现Runnable是一个更好的选择。
耦合 扩展Thread类引入了紧密耦合,因为该类包含Thread类的代码以及分配给该线程的作业实施Runnable接口会引入松散耦合,因为Thread的代码与Thread的工作是分开的。


线程类的定义

线 是在 java.lang 包。 Thread类扩展了 宾语 类,并实现 可运行 接口。 Thread类具有用于在线程上创建和操作的构造函数和方法。当我们创建多个线程时,每个线程都会创建一个唯一的对象并与该对象关联。如果创建一个扩展Thread类的线程,则进一步将无法扩展任何其他类,因为Java不支持多重继承。因此,仅当您还想覆盖Thread类的其他一些方法时,才应该选择扩展Thread类。让我们看一个创建扩展Thread类的线程的示例。

/ *定义线程* /类Mythread扩展了线程{/ *线程的工作* / public void run(){for(int i = 0; i <10; i ++){System.Out.ln(“子线程” ); }}类mainThread {/ *主线程的工作* / public static void main(String args){Mythread mt = new Mythread(); / *主线程创建了子线程* / mt.start(); for(int i = 0; i <10; i ++){System.Out。(“主线程”); }}} / * Output * /主线程主线程主线程主线程子线程子线程子线程子线程子线程子线程主线程子线程子线程主线程主线程子线程子线程子线程主线程主线程子线程子线程子线程子线程主线程

在上面的代码中,我创建了一个MyThread类,该类扩展了Thread类并覆盖了Thread类的run方法。在包含main方法的类中,我创建Mythread类的线程对象(mt),并使用该线程对象调用了start()方法。 start方法启动线程的执行,同时JVM调用线程的run方法。现在程序中有两个线程,一个是主线程,另一个是由主线程创建的子线程。两个线程的执行同时发生,但是不能假装确切的输出。

可运行接口的定义

可运行 是一个接口 java.lang 包。实现Runnable接口,我们可以定义一个线程。可运行接口具有单一方法 跑(), 由实现Runnable接口的类实现。当您选择定义实现Runnable接口的线程时,您仍然可以选择扩展任何其他类。通过实现Runnable接口创建多个线程时,每个线程共享相同的可运行实例。让我们学习如何使用Runnable接口定义线程。


/ *定义线程* /类Runnablethread实现了Runnable {/ *线程的工作* / public void run(){for(int i = 0; i <10; i ++){System.Out.ln(“子线程” ); }}类mainThread {/ *主线程的工作* / public static void main(String args){Mythread rt = new Mythread(); / *主线程创建了可运行对象* /线程t =新线程(rt); / *主线程创建子线程并传递可运行对象* / t.start(); for(int i = 0; i <10; i ++){System.Out。(“主线程”); }}} / * Output * /主线程主线程主线程主线程子线程子线程子线程子线程子线程子线程主线程子线程子线程主线程主线程子线程子线程子线程主线程主线程子线程子线程子线程子线程主线程

在上面的代码中,我创建了一个Runnablethread类,该类实现Runnable接口,并通过实现Runnable接口的run()方法来定义线程的作业。然后,我创建一个包含main方法的类mainthread。在main方法中,我声明了Runnablethread类的runnable对象,并在声明线程的同时将此对象传递给Thread的构造函数。这样,我将线程对象(t)与可运行对象(rt)链接在一起。然后,线程对象调用线程的start方法,该方法进一步调用Runnablethread类的run方法。如果我没有将可运行对象与Thread对象链接,则线程start方法将调用Thread类的run方法。现在,再次在代码中有两个线程,主线程和主线程创建子线程都同时执行,但是永远都不能假装确切的输出。

Java中线程和可运行代码之间的主要区别

  1. 通过扩展Thread类创建的每个线程都会为其创建一个唯一的对象,并与该对象关联。另一方面,通过实现Runnable接口创建的每个线程共享同一可运行实例。
  2. 由于通过扩展Thread类创建的每个线程都与一个唯一的对象相关联,因此需要更多的内存。另一方面,通过实现Runnable接口创建的每个线程共享相同的对象空间,因此需要更少的内存。
  3. 如果进一步扩展Thread类,则可以继承任何其他类,因为Java不允许多重继承,而实现Runnable仍然为类提供了继承其他任何类的机会。
  4. 只有在必须重写或专用于Thread类的某些其他方法时,才必须扩展Thread类。如果只想专门运行方法,则必须实现Runnable接口。
  5. 扩展Thread类会在代码中引入紧密耦合,因为Thread的代码和线程的工作都包含在同一类中。另一方面,由于Thread的代码与分配给该线程的作业是分开的,所以实现Runnable接口在代码中引入了松散耦合。

结论:

最好实现一个Runnable接口,而不是扩展Thread类。由于线程的代码不同于将作业分配给线程的类,因此实现Runnable会使您的代码松散耦合。它需要较少的内存,并且还允许一个类继承任何其他类。