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 支付矩阵在市场竞争策略分析中的应用 支付矩阵是一种强大的决策工具,它在多个领域的应用中都发挥着重要作用。以下是一个具体的应用案例…

241029算法学习

问题1 : 一根高筋拉面,中间切一刀,可以得到2根面条。 如果先对折1次,中间切一刀,可以得到3根面条。 如果连续对折2次,中间切一刀,可以得到5根面条。 那么,连续对折10次,中…

五指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…

华为OD机试真题---狼羊过河

关于华为OD机试真题中的“狼羊过河”问题,实际上更准确地描述应该是“羊、狼、农夫过河”问题。这个问题是一个经典的逻辑问题,要求在满足特定条件下,利用一艘有限容量的船将羊和狼全部安全地运送到对岸。以下是对该问题的详细解析&#xff1…

【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 (访问密钥)

快速上手 Rust——环境配置与项目初始化

Rust 跨界:全面掌握跨平台应用开发 第一章:快速上手 Rust 1.1 环境配置与项目初始化 1.1.1 安装 Rust 和 Cargo 在开始学习 Rust 之前,首先需要安装 Rust 编程语言及其包管理工具 Cargo。Rust 的安装非常简单,使用官方的安装脚…

基于langchain框架的智能PDF问答(一)创建向量数据库

首先安装langchain,安装完之后就可以开始我们的步骤了 pip install langchain第一步 我们可以先创建一个Python文件,用于将PDF加载到我们本地的向量数据库中 一、读取文档 加载PDFX需要用到文本加载器,导入PyPDFLoader这个函数 #读取文档 from langchain.documen…

开源呼叫中心系统FreeIPCC:SIP 协议详解

SIP 协议详解大全 作者:开源呼叫中心系统FreeIPCC SIP(Session Initiation Protocol,会话初始协议)是由IETF(Internet Engineering Task Force,因特网工程任务组)制定的多媒体通信协议。它最早…

机器学习认知包

开源竞争: 开源竞争(自己没有办法完全掌握技术的时候就开源掉,培养出更多的技术依赖,让更多的人完善你的技术,那么这不就是在砸罐子吗?一个行业里面你不去砸罐子,其他人就会砸罐子,你…

北京迅为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…