Java中的多线程详解(超级简单理解)(上篇)

使用工具 IntelliJ IDEA Community Edition 2023.1.4

使用语言 Java8 

代码能力快速提升小方法,看完代码自己敲一遍,十分有用 

目录

1.多线程概述

1.1 进程与线程

1.2 多线程的运行机制

1.3 多线程的优势 

2.多线程编程

2.1 Thread类介绍 

2.2 继承Thread类创建线程类

2.2.1 Thread类贯穿示例 

2.3 实现Runnable接口创建线程类 

2.3.1 Runnable接口贯穿示例

3.线程的状态转换

3.1 状态转换 

3.2 状态转换详解 

3.3 状态转换贯穿示例


1.多线程概述

世间万物中每个个体都可以同时完成很多工作。例如,人体可以同时进行呼吸、血液循环、思考问题等活动。用户既可以使用计算机听歌,也可以编写文档、发送文件等,这些活动可以同时进行。在计算机领域里,这种同时执行多个操作的行为模式被称为并发。在操作系统中同时运行着多个独立的任务,每个任务对应一个进程,每个进程可产生多个线程。通过这种并发运行的方式,计算机的性能被挖掘到了极限。

1.1 进程与线程

进程是程序的一次动态执行过程,它是从代码加载、执行中到执行完毕的一个完整过程,也是进程本身从产生、发展到最终消亡的过程。操作系统同时管理一个计算机系统中的多个进程,让计算机系统中的多个进程轮流使用中央处理器(Central Processing Unit,CPU)资源,或者共享操作系统的其他资源。由于CPU执行速度非常快,所有程序好像是在"同时"运行一样。
操作系统中可以有多个进程,这些进程包括系统进程(由操作系统内部建立的进程)用户进程(由用户程序建立的进程)。可以从Windows任务管理器中查看已启动的进程,进程是系统运行程序的最小单元。各进程之间是独立的,每个进程的内部数据和状态也是完全独立的。
线程是进程中执行运算的最小单位,是在进程基础上的进一步划分,一个线程可以完成一个独立的顺序控制流程。下面看一个简单的问题,假设一个水箱有五个排水孔,打开一个排水孔清空水箱要一个小时,怎样才能使水箱迅速清空并计算最快的清空事件?如果把水箱排水比作一个进程,那么一个排水孔就是一个线程。
与进程不同,同一进程内的多个线程共享同一块内存空间(包括代码空间、数据控件)和一块系统资源,所以系统在产生一个线程或在各线程之间切换工作时,其负担要比在进程间切换小得多。 

综上所述,进程和线程是两个不同的概念。应用程序有单进程单线程的,有多进程但每个进程只有一个线程的,有单进程包含多线程的,还有多进程且每个进程都有多个线程等四种情况。

如果在同一个进程中同时有多个线程,用于执行不同的工作,被称之为"多线程"。这些线程可以同时存在、同时执行。例如,只有一个排水孔的水箱可以比作单线程程序,有多个排水孔的水箱可比作多线程程序。

1.2 多线程的运行机制

以往开发的程序大多是多线程的,即一个程序只有从开始到结束这一条执行路径。而多线程是指一个进程同时存在几条执行路径且并发执行的工作方式。
并发运行与并行运行不同。并行运行通常表示同一个时刻有多条指令代码在处理器上同时运行,这种情况往往需要多个处理器支持。而并发运行表示在一个处理器中,操作系统为了提高程序的运行效率,将CPU的执行时间分成多个时间片,分配给同一进程的不同线程。当执行完一个时间片后,当前运行的线程就可能交付出CPU权限,让其他线程执行下一个时间片,当然CPU也有可能将相邻的时间片分配给同一线程,即多个线程分享CPU时间,交替运行。之所以从表面上看是多个线程同时运行的,是因为不同线程之间切换的时间非常短,也许仅仅是几毫秒,对普通人来说是难以感知的,即所谓的"宏观并行,微观串行" 。

由于进程和线程含义不同,所以运行多个进程和多个线程是不同的。运行多个进程指在同一段时间内,可以同时运行一个以上的程序,即多个任务同时执行。例如,一边浏览网页,一边听音乐。而运行多个线程指在同一个程序内同时运行一个以上的子程序,如使用网盘同时下载多个文件。

1.3 多线程的优势 

多线程作为一种多任务并发的工作方式,有着广泛的应用。合理使用线程,将减少开发和维护的成本,甚至可以改善复杂应用程序的性能。使用多线程的优势如下: 

优势

  • 充分利用CPU的资源。运行单线程程序时,若程序发生阻塞,则CPU可能会处于空闲状态,这将造成计算机资源浪费。而使用多线程可以在某个线程处于休眠或阻塞状态时运行其他线程,这将大大提高资源利用率。
  • 简化编程模型。可以考虑将一个既长又复杂的进程分为多个线程,成为几个独立执行的模块,如使用时、分、秒来描述当前时间。如果时单线程程序,则需要多重判断。如果使用多线程,时,分,秒各使用一个线程控制,每个线程仅需实现简单的流程,简化了程序逻辑,更方便编码和维护。
  • 良好的用户体验。由于有多个线程可以交替运行,减少或避免了程序阻塞或意外情况造成的响应过慢现象,减少了用户等待时间,提升了用户体验。

多线程技术在实际开发中时非常有价值的。例如,Word文本编辑工具需提供一边编辑一边保存的功能,且同时进行规范化格式和标记错别字检查;应该浏览器必须能同时下载多个图片;一个Web服务器必须能同时响应多个用户请求;JVM本身就在后台提供了一个超级线程进行垃圾回收.......总之,多线程在实际编程中的应用是非常广泛的。 

2.多线程编程

Java语言提供了java.lang.Thread类支持多线程编程;

2.1 Thread类介绍 

Thread类提供了大量的方法来控制和操作线程。Thread类的常用方法如下:

Thread()创建Thread对象构造方法
Thread(Runnable target)        创建Thread对象,target为run()方法被调用的对象构造方法
Thread(Runnable target,String name)创建Thread对象,target为run()方法被调用的对象,name为新线程的名字构造方法
void run()执行任务操作的方法实例方法
void start()使该线程开始运行,JVM将调用该线程的run方法
一般使用这个,不直接调用run方法
实例方法
void sleep()在指定的毫秒数内让当前正在运行的线程休眠(暂停运行)静态方法
Thread currentThread()返回当前线程对象的引用静态方法

Thread类的静态方法currentThread()方法返回当前线程对象的引用。在Java程序启动时,一个线程立即随之启动,这个线程通常被称为程序的主线程。public static void main()方法是主线程的入口,每个进程至少有一个主线程。它的重要性如下:

  • 主线程是产生其他子线程的线程
  • 主线程通常必须最后完成运行,因为它执行各种关闭工作 

尽管主线程是自动创建的,但是可以由一个Thread对象控制。因此,可以使用Thread类的方法获取主线程信息。
在Java语言中,实现多线程的方式有两种:一种是继承Thread类,另一种是实现Runnable接口。 

2.2 继承Thread类创建线程类

继承Thread类是实现线程的一种方式。在使用此方法自定义线程类时,必须在格式上满足以下要求:

  • 此类必须继承Thread类
  • 将线程执行的代码写在run()方法中

线程从它的run方法开始执行,即run()方法时线程执行的起点,就像main()方法是应用程序的起点一样。因为run()方法定义在Thread类中,所以在自定义线程类中必须重写run()方法,为线程提供实现具体任务的代码。

2.2.1 Thread类贯穿示例 

示例代码 

 

运行结果 

 

后面的循环内容将会每隔2秒打印一句

注意:
1.已启动的线程对象(就是同一个线程对象)不能重复调用start()方法,否则会抛出IllegalThreadStateException异常。
2.sleep()方法用来控制线程的休眠时间。如果这个线程被其他线程中断,则会产生InterruptedException异常。所以sleep()方法必须进行异常处理。 

线程对象调用start方法和调用run方法截然不同。前者是启动线程,后者是调用实例方法,在实际应用中切不要混淆。

2.3 实现Runnable接口创建线程类 

在使用继承Thread类的方式创建线程的过程中,子类无法再继承其他父类。这是因为Java语言不支持多重继承。在这种情况下,可以通过实现Runnable接口的方式创建线程这种方式更具有灵活性,用户线程还可以通过继承,再具有其他的特性,这是开发中经常使用的方式
Runnable接口位于java.lang包中,其中只提供一个抽象方法run()的声明,Thread类也实现了Runnable接口。使用Runnable接口时也列表框Thread类,这是因为它要用到Thread类中的start()方法。在Runnable接口中只有run()方法,其他操作都要借助于Thread类。使用Runnable接口创建线程的一般格式如下。 

2.3.1 Runnable接口贯穿示例

示例代码 

 

运行结果 

 

后面的循环内容将会每隔2秒打印一句
在以上代码中,虽然TestRunnable类为线程提供了run()方法,但它本身不是线程类。如果创建一个专门执行run()方法的线程对象,则需要创建一个Thread对象。
TestRunnable类实现了Runnable接口,在run()方法中编写线程所执行的代码。如果TestRunnable需要继承其他类,也完全可以实现。 

3.线程的状态转换

3.1 状态转换 

Java语言使用Thread类及其子类的对象表示线程,新建的线程通常会在五种状态中转换,即新建(new)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。这五种状态组成了线程的生命周期,如下所示: 

3.2 状态转换详解 

新建状态。一个Thread类或其子类的对象被声明并创建,但其还在未启动的这段时间里处于一种特殊的新建状态中。此时,线程类对象已经被分配了内存空间和资源,并且已被初始化,但是该线程尚未被调度;
就绪状态。就绪状态也被称为可运行状态,处于新建状态的线程被启动后,也就是调用start()方法后,新建线程将进入线程队列,排队等待CPU时间片。此时它已具备运行的条件,一旦轮到它使用CPU资源,他就可以脱离创建它的主线程独立开始它的生命周期。这就好比一批作物种子被运输到农场,处于等待果农撒种的状态。
运行状态。当就绪状态的进程被调度并获得处理器资源后便进入运行状态,该状态表示线程正在运行,该线程已经拥有了CPU的占用券。这就好比作物种子被农夫种植到土地里,在阳光的照耀和雨水的浇灌下生根、发芽、茁壮成长。
当调用start()方法后,线程获取资源运行run()方法中的代码,代码进入运行状态。每个Thread类及其子类都拥有一个线程操作方法run(),当线程类对象被调度运行时,它将自动调用此run()方法,从该run()方法的第一条语句开始执行,一直到执行完毕。处于运行状态的线程在以下四种情况下会让出CPU的控制权。

  • 线程运行完毕
  • 有比当前线程优先级更高的线程抢占了CPU
  • 线程休眠
  • 线程因等待某个资源而处于阻塞状态

阻塞状态。一个正在运行的线程在某些特殊情况下需要让出CPU并暂时中止运行。这时,线程处于不可运行的状态被称为阻塞状态。这就好比作物在生长过程中由于干旱少雨或遭遇虫害停滞生长。
导致线程死亡的原因有两个:一时正常运行的线程完成了它的全部工作,即运行完run()方法的最后一条语句并退出;二时当进程停止运行时,该进程中的所有线程将被强行中止。线程处于死亡状态并且没有该线程的引用是,JVM会从内存中删除该线程类对象。 

简而言之,忽略操作系统底层的操作,在程序中可视的线程生命周期是新建线程、start()方法启动线程、调用run()方法运行线程,运行完毕后线程的生命周期就结束了。 

3.3 状态转换贯穿示例

示例代码 

运行结果

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Java中的SSM框架实现电能计量与客户服务管理系统项目【项目源码+论文说明】

基于Java中的SSM框架实现电能计量与客户服务管理系统演示 摘要 当前时代的两个突出特征是世界经济一体化和以计算机为代表的信息技术的迅速发展。为了使组织在激烈的竞争中保持实力和发展,它必须对迅速变化的环境做出有效而有效的响应。 管理信息系统的应用可以提供…

Linux系统安装openGauss结合内网穿透实现公网访问本地数据库管理系统——“cpolar内网穿透”

文章目录 前言1. Linux 安装 openGauss2. Linux 安装cpolar3. 创建openGauss主节点端口号公网地址4. 远程连接openGauss5. 固定连接TCP公网地址6. 固定地址连接测试 前言 openGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行。openGauss内核深度融合…

6SL3126-1TE21-8AA4单电机模块质保一年

商品编号(市售编号) 6SL3126-1TE21-8AA4 SINAMICS S120 单电机模块 输入:600V DC 输出:3AC 400V,18A 结构形式:书本尺寸 冷板冷却 优化的脉冲图形和 支持扩展 安全集成功能 包含 DRIVE-CLiQ 电缆 列表价(不含税&#xff09…

查询正在运行的Top SQL的脚本(建议收藏)

这篇文章提供了一些现成的SQL脚本,通过查询V$SQLSTATS视图找到正在运行的TOP SQL,用于后续的优化。建议大家收藏,需要查询TOP SQL时直接复制和粘贴即可。 之前的一篇文章解释了为什么要使用V$SQLSTATS视图。 当数据库表现出各种不同的性能问…

MATLAB环境基于健康指标(Health indicator)的滚动轴承故障诊断

轴承的剩余使用寿命RUL预测过程一般包括以下三个步骤:(1)数据采集,(2)健康指标HI构建,(3)RUL预测。在预测过程中,RUL并不能直接依靠观测得到,其主…

智慧水务:雨季山区水域水务智能化监控与监测管理方案

一、方案背景 雨季的水务管理对于各区县来说,无疑是一项至关重要的任务。夏季雨水充沛,江河湖泊水位上涨,山洪、上游排水等情况时有发生,给各地的水务设施和防汛工作带来了严峻的挑战。针对区县的各类水域监管场景,需…

欧润金:抗衰生意火爆?抗老制品受富裕中产追捧,抢购难求!

当人们物质财富积累到一定程度后,他们开始踏上“用金钱留住时间”的探寻之路。 亚马逊创始人贝索斯为解锁“青春密码”,投资30亿美元建造生物研究所Alots;硅谷富豪莱恩约翰逊每年豪掷上百万美元,用于自己的健康管理;世…

JavaSE—IO流之字符流

📌 字符流中的常用类及基本方法: 输入字符流 Reader输出字符流 Writer ○ Reader 的基本方法: • 读取一个字符并以整数的形式返回, 如果返回-1已到输入流的末尾。 int read() throws IOException • 读取一系列字符并存储到一个数组buff…

OPPO案例 | Alluxio在DataAI湖仓一体的实践

分享嘉宾: 付庆午-OPPO数据架构组大数据架构师 在OPPO的实际应用中,我们将自研的Shuttle与Alluxio完美结合,使得整个Shuttle Service的性能得到显著提升,基本上实现了性能翻倍的效果。通过这一优化,我们成功降低了约一…

【免费】教你如何考取腾讯云《云函数 SCF》认证

云函数 SCF考试PC网址 云函数 SCF - 认证中心 - 腾讯产业互联网学堂 (tencent.com) 注:免费认证,里面包含免费的课程,浏览器用Edge。 文章目录 目录 文章目录 前言 一、备考流程 二、注意事项 总结 前言 随着云计算的不断发展&#xf…

基于word2vec+LSTM模型实现百度贴吧恶意评论预测

大家好,我是带我去滑雪! Word2Vec模型能够将词语映射到高维空间中的向量表示,同时保留了词语之间的语义信息和上下文关系。这使得模型能够更好地理解评论中的语境和含义。LSTM模型是一种适用于处理序列数据的深度学习模型,能够有效…

面对淘天的升级,如果说我们要在渠道运营端口做出一些改变,最重要、最应该、最优先的是什么?|淘天商品API数据采集接口

2024年,电商真正跨入了新AI时代。 在这个新时代,工具、方法、体系……都在升级,堪称一日千里。 商家如何更好地顺应时代的变化?2024年,我给大家的建议总结为两句话。 第一句是借平台的红利; 第二句是建立自…

【VTKExamples::Points】第十期 NormalEstimation

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例NormalEstimation,并解析接口vtkPCANormalEstimation,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力…

I.MX6ULL_Linux_驱动篇(55)linux 网络驱动

网络驱动是 linux 里面驱动三巨头之一, linux 下的网络功能非常强大,嵌入式 linux 中也常常用到网络功能。前面我们已经讲过了字符设备驱动和块设备驱动,本章我们就来学习一下linux 里面的网络设备驱动。 嵌入式网络简介 网络硬件接口 首先…

【C语言】tcp_sendmsg_locked

一、讲解 tcp_sendmsg_locked 函数是 Linux 内核中实现 TCP 数据发送的一个核心函数。这个函数被调用来将用户空间的数据通过 TCP 发送出去。以下是该函数的基本工作流程的中文解释: 1. 函数初始化和检查: - 它首先检查是否使用了 TCP 零拷贝发送&am…

【微服务】Spring Boot 版本升级到 2.7.18

前言 目前项目上扫描出一些 Java 依赖的代码漏洞&#xff0c;需要对现有依赖版本升级&#xff0c;记录一下遇到的问题。 <spring-boot.version>2.3.2.RELEASE</spring-boot.version> <spring-cloud.version>Hoxton.SR9</spring-cloud.version> <s…

RuoYi-Vue-Plus(登录流程-验证码生成)

一、登录流程 1- 进入登录页面&#xff0c;调用 com.ruoyi.web.controller.common.CaptchaController 类中的 captchaImage 方法&#xff0c;生成base64的图片 以及 UUID 2- 提交 登录信息 验证码 uuid 比对 错误&#xff1a;返回错误信息&#xff0c;删除缓存的验证码 成功…

一个优秀的开源ChatGpt外壳项目(lobe-chat)

lobe-chat 简介&#xff1a; 开源、现代化设计的 ChatGPT/LLMs 聊天应用与开发框架支持语音合成、多模态、可扩展的插件系统&#xff0c;一键免费拥有你自己的 ChatGPT/Gemini/Ollama 应用。 下载lobe-chat lobe-chat项目开源地址&#xff1a;GitHub - lobehub/lobe-chat: &am…

MySQL高可用解决方案――从主从复制到InnoDB Cluster架构

2024送书福利正式起航 关注「哪吒编程」&#xff0c;提升Java技能 文末送5本《MySQL高可用解决方案――从主从复制到InnoDB Cluster架构》 大家好&#xff0c;我是哪吒。 爱奇艺每天都为数以亿计的用户提供7x24小时不间断的视频服务。通过爱奇艺的平台&#xff0c;用户可以…

查看Linux系统重启的四种基本命令

目录 前言1. last2. uptime3. journalctl4. dmesg 前言 对于排查其原因推荐阅读&#xff1a;详细分析服务器自动重启原因&#xff08;涉及Linux、Window&#xff09; 在Linux中&#xff0c;有多种命令可以查看系统重启的信息 以下是其中一些常用的命令及其解释&#xff1a; …