Java中创建线程的两种方式与区别

在Java中,创建线程是并发编程的基础。Java提供了多种方式来创建线程,其中两种最常见的方式是继承Thread类和实现Runnable接口。这两种方式各有优缺点,适用于不同的场景。下面将对这两种方式进行详细的介绍和比较。

一、继承Thread

1. 基本原理

通过继承Thread类来创建线程是Java中最直接的一种方式。Thread类是Java中所有线程的基类,它提供了线程的基本属性和方法。当创建一个类继承Thread类后,可以通过重写Thread类中的run方法来定义线程的行为。然后,通过创建该类的实例并调用其start方法,就可以启动一个新的线程。

2. 示例代码

以下是一个简单的示例,展示了如何通过继承Thread类来创建和启动线程:

public class MyThread extends Thread {
@Override
public void run() {
// 线程要执行的代码
System.out.println("MyThread is running");
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start(); // 启动线程
}
}

在这个示例中,我们创建了一个名为MyThread的类,它继承自Thread类并重写了run方法。然后,在main方法中,我们创建了MyThread的实例并调用了其start方法来启动线程。

3. 优点
  • 简单直接:通过继承Thread类,可以很容易地创建和启动线程,不需要额外的接口或类。
  • 易于理解:对于初学者来说,继承Thread类的方式相对直观,容易理解线程的创建和启动过程。
4. 缺点
  • 单继承限制:Java只支持单继承,如果一个类已经继承了另一个类,那么它就不能再继承Thread类来创建线程。这限制了类的扩展性。
  • 耦合度高:继承Thread类的方式将线程的任务逻辑与线程的管理逻辑紧密地结合在一起,这不利于代码的解耦和复用。

二、实现Runnable接口

1. 基本原理

实现Runnable接口是Java中创建线程的另一种常见方式。Runnable接口定义了一个run方法,该方法包含了线程要执行的代码。与继承Thread类不同,实现Runnable接口的类并不直接成为线程类,而是需要将其实例作为参数传递给Thread类的构造方法,然后调用Thread对象的start方法来启动线程。

2. 示例代码

以下是一个简单的示例,展示了如何通过实现Runnable接口来创建和启动线程:

public class MyRunnable implements Runnable {
@Override
public void run() {
// 线程要执行的代码
System.out.println("MyRunnable is running");
}
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start(); // 启动线程
}
}

在这个示例中,我们创建了一个名为MyRunnable的类,它实现了Runnable接口并重写了run方法。然后,在main方法中,我们创建了MyRunnable的实例,并将其作为参数传递给Thread类的构造方法来创建Thread对象。最后,我们调用了Thread对象的start方法来启动线程。

3. 优点
  • 灵活性高:实现Runnable接口的方式不受单继承的限制,一个类可以实现多个接口,因此可以更加灵活地定义线程的行为。
  • 解耦性好:实现Runnable接口的方式将线程的任务逻辑与线程的管理逻辑分离开来,这有利于代码的解耦和复用。例如,可以将多个Runnable对象传递给同一个Thread对象来执行不同的任务,或者将Runnable对象提交给线程池来管理。
  • 易于共享资源:由于Runnable对象不是线程本身,因此可以更容易地在多个线程之间共享资源。例如,可以创建多个Runnable对象来访问同一个数据集合,从而实现并发处理。
4. 缺点
  • 相对复杂:与继承Thread类相比,实现Runnable接口的方式需要额外的步骤来创建Thread对象并启动线程。这增加了代码的复杂性。
  • 抽象层次高:实现Runnable接口的方式更加抽象,对于初学者来说可能不太容易理解线程的具体实现和启动过程。

三、两种方式的比较

1. 灵活性

实现Runnable接口的方式在灵活性方面优于继承Thread类的方式。由于Java只支持单继承,如果一个类已经继承了另一个类,那么它就不能再继承Thread类来创建线程。而实现Runnable接口则不受这个限制,一个类可以实现多个接口,因此可以更加灵活地定义线程的行为。此外,实现Runnable接口的方式还可以将线程的任务逻辑与线程的管理逻辑分离开来,这有利于代码的解耦和复用。

2. 耦合度

继承Thread类的方式将线程的任务逻辑与线程的管理逻辑紧密地结合在一起,这不利于代码的解耦和复用。而实现Runnable接口的方式则可以将这两者分离开来,使得代码更加清晰和易于维护。

3. 资源共享

实现Runnable接口的方式在资源共享方面也具有优势。由于Runnable对象不是线程本身,因此可以更容易地在多个线程之间共享资源。例如,可以创建多个Runnable对象来访问同一个数据集合,从而实现并发处理。而继承Thread类的方式则可能需要额外的同步机制来确保线程之间的资源访问是安全的。

4. 编程习惯

在实际编程中,实现Runnable接口的方式往往被更多地采用。这是因为实现接口是一种更加面向对象和灵活的方式,它允许一个类实现多个接口而不受单继承的限制。此外,许多Java框架和库(如Java的并发包java.util.concurrent)也倾向于使用Runnable接口来定义并发任务。

四、其他创建线程的方式

除了继承Thread类和实现Runnable接口之外,Java还提供了其他几种创建线程的方式:

  1. 使用匿名内部类:可以通过匿名内部类来创建Thread子类对象或实现Runnable接口的对象,从而简化代码。这种方式在需要创建简单的线程任务时非常有用。
  2. 使用Lambda表达式:在Java 8及更高版本中,可以使用Lambda表达式来创建线程。这种方式更加简洁和易于理解,特别是在需要传递简单的函数式接口(如Runnable)时。
  3. 实现Callable接口:与Runnable接口类似,Callable接口也可以用于定义线程的任务。不同之处在于,Callable接口的任务可以返回值并且可以抛出异常。要实现Callable接口的任务,需要将其包装在FutureTask对象中,并将其作为参数传递给Thread类的构造方法。然后,可以通过调用FutureTask对象的get方法来获取线程的返回值。
  4. 使用线程池:线程池是一种管理线程的技术,它可以提高程序的性能和响应速度。通过线程池,可以重用现有的线程来执行新的任务,而不是每次都创建新的线程。Java的并发包java.util.concurrent提供了多种线程池实现,如ExecutorServiceScheduledExecutorService等。

五、总结

Java中创建线程的方式有多种,其中继承Thread类和实现Runnable接口是最常见的两种方式。这两种方式各有优缺点,适用于不同的场景。继承Thread类的方式简单直接,但受单继承限制且耦合度高;实现Runnable接口的方式则更加灵活和解耦性好,但相对复杂且抽象层次高。在实际编程中,应根据具体需求和场景选择合适的方式来创建线程。同时,也可以考虑使用其他创建线程的方式(如匿名内部类、Lambda表达式、Callable接口和线程池)来简化代码和提高性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/883849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PPT批量替换字体

1.【开始】➡【查找】➡【替换字体】。 2.在弹窗内选择替换字体,和想要换成的字体,设置好点击【替换】,然后点击【关闭】或者左上角的小【】。 3.可以检查一下,每一页的【宋体】或者其他字体,都被改成了【微软雅黑】…

模型 支付矩阵

系列文章 分享 模型,了解更多👉 模型_思维模型目录。策略选择的收益分析工具。 1 支付矩阵的应用 1.1 支付矩阵在市场竞争策略分析中的应用 支付矩阵是一种强大的决策工具,它在多个领域的应用中都发挥着重要作用。以下是一个具体的应用案例…

五指cms安装

我在安装五指cms的过程中发现一个问题,我看到的大部分的安装指导并没有详细的告诉大家该怎样做。所以我写这篇博客来进行一个比较详细的指导。 第一步:解压我们的wuzhicms文件并将其移动到phpstudy的WWW文件目录下。 第二步: 在phpstudy配置…

3个模型的交互式多模型IMM,基于EKF的目标跟踪实例(附MATLAB代码)

文章目录 3个模型的IMM源代码运行结果代码介绍总结 3个模型的IMM 代码实现了基于 I M M IMM IMM(Interacting Multiple Model)算法的目标跟踪。它使用三种不同的运动模型(匀速直线运动、左转弯和右转弯)来预测目标的位置&#x…

OpenCV视觉分析之目标跟踪(4)目标跟踪类TrackerDaSiamRPN的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::TrackerDaSiamRPN 是 OpenCV 中用于目标跟踪的一个类,它实现了 DaSiam RPN(Deformable Siamese Region Proposal Net…

【Linux系统编程】第三十九弹---探索信号处理的奥秘:阻塞信号与sigset_t的深入剖析及实战

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、信号处理 2、阻塞信号 2.1、信号其他相关常见概念 2.2、在内核中的表示 2.3、sigset_t 2.4、信号集操作函数 3、完整…

QNAP威联通NAS设置了仅允许列表内的计算机连接,但是忘记有效IP地址怎么访问

创作立场:原创不易,拒绝搬运~ hello 大家好,我是你们的老伙伴,稳重的大王~ 本期教程为大家介绍一个使用场景的故障解除办法,如果遇到类似问题,可以参考一下解题思路~ 如上图所示位置,不小心设…

LabVIEW非接触式模态参数识别系统开发

基于LabVIEW的模态参数识别系统采用非接触式声学方法,结合LabVIEW软件和高精度硬件,实现机械结构模态参数的快速准确识别。降低了模态分析技术门槛,提高测试效率和准确性。 项目背景与意义: 传统的模态分析方法,如锤击法&#x…

ssm011线上旅行信息管理系统(论文+源码)_kaic

毕业论文(设计) 题 目:线上旅行信息管理系统设计与实现 姓  名: 专  业: 班  级: …

【RAG实战】优化索引的四种高级方法,快点收藏起来!!

前言 Indexing(索引)是搭建任何RAG系统的第一步,也是至关重要的一步,良好的索引意味着合理的知识或信息分类,召回环节就会更加精准。在这篇文章中,围绕Indexing(索引)环节&#xff…

【火山引擎】文生图实践 | PYTHON

目录 1 准备工作 2 实践 1 准备工作 ① 服务开通 确保已开通需要访问的服务。可前往火山引擎控制台并开通相应服务。 ② 获取安全凭证 Access Key (访问密钥)

北京迅为iTOP-LS2K0500开发板快速使用编译环境虚拟机Ubuntu基础操作及设置

迅为iTOP-LS2K0500开发板 迅为iTOP-LS2K0500开发板采用龙芯LS2K0500处理器,基于龙芯自主指令系统(LoongArch)架构,片内集成64位LA264处理器核、32位DDR3控制器、2D GPU、DVO显示接口、两路PClE2.0、两路SATA2.0、四路USB2.0、一路…

浏览器HTTP缓存解读(HTTP Status:200 304)

为什么要有浏览器缓存? 浏览器缓存(Brower Caching)是浏览器对之前请求过的文件进行缓存,以便下一次访问时重复使用,节省带宽,提高访问速度,降低服务器压力 http缓存机制主要在http响应头中设定,响应头中…

(蓝桥杯C/C++)——常用库函数

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 一、 二分查找 1.二分查找的前提 2.binary_ search函数 3.lower_bound和upper_bound 二、排序 1.sort概念 2.sort的用法 3.自定义比较函数 三、全排列 1.next p…

Spring Boot⾃动配置

一、Spring Boot的自动配置原理 Spring Boot使用一种称为“约定优于配置”的方法,这意味着如果你按照预定的方式来安排你的代码和依赖项,Spring Boot可以自动配置你的应用程序。主要特点包括: 自动检测:Spring Boot在应用启动时…

C#实现word和pdf格式互转

1、word转pdf 使用nuget: Microsoft.Office.Interop.Word winform页面: 后端代码: //using Spire.Doc; //using Spire.Pdf; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using Sy…

iOS Swift5算法恢复——HMAC

demangle的时候看到了CryptoSwift,HMAC,于是写一个helloworld,用于对照。 sudo gem install cocoapods pod init pods文件,注意要标注静态链接: # Uncomment the next line to define a global platform for your p…

Diving into the HAL-----HAL_GPIO

1、怎么看待外设: 从总线连接的角度看,外设和Core、DMA通过总线交换数据,正所谓要想富先修路。要注意,这些总线中的每一个都连接到不同的时钟源,这些时钟源决定了连接到该总线的外设操作的最大速度。 从内存分配的角度…

C#与C++交互开发系列(十六):使用多线程

前言 在开发需要高性能的应用程序时,多线程是提升处理效率和响应速度的关键技术。C 和 C# 各自拥有不同的线程模型和并发工具。在跨语言开发中,如何有效地利用两者的并发特性,同时确保线程安全和数据一致性,是一个值得探讨的问题…

libavdevice.so.58: cannot open shared object file: No such file ordirectory踩坑

博主是将大图切分成小图时遇到 问题一、linux编译后,找不到ffmpeg中的一个文件 产生原因,各种包集成,然后安装以后乱七八糟,甚至官方的教程也不规范导致没有添加路径到系统文件导致系统执行的时候找不到 1.下载 博主进行的离线…