Java零基础之多线程篇:线程生命周期
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
在并发编程中,多线程是一种非常重要的技术手段,理论知识及线程创建我已经在上一章节讲过了,本章我们就不再赘述。我们都知道Java作为一种广泛应用的开发语言,提供了丰富的多线程编程支持。了解并掌握Java多线程的生命周期对于编写高效且可靠的多线程程序至关重要。所以在本文中,我将介绍Java多线程的生命周期,包括线程状态的转换和对应的方法调用,作为新一期的内容进行讲解,这也是为了帮助大家学习上能够循序渐进。
摘要
本文我的讲解思路是:首先通过简介介绍Java多线程的基本概念和特性,然后深入探讨线程的生命周期,包括线程的状态转换和相关的方法调用。此外,本文还将通过源代码解析、应用场景案例和优缺点分析等方式,帮助读者更好地理解和应用线程的生命周期。
简介
多线程是指在一个程序中同时进行多个线程的执行,每个线程具有独立的执行路径。在Java中,每个线程都有自己的生命周期,包括新建、就绪、运行、阻塞和终止等不同状态。线程状态的转换由Java虚拟机自动控制,但是开发人员可以通过方法调用来干预线程的状态。
源代码解析
在Java中,创建一个线程最常见的方式是继承Thread类或实现Runnable接口。以下是一个简单的示例代码:这里我们主要是以回顾+温习为主,毕竟上一章节已经学完的内容。
/*** @Author ms* @Date 2024-04-12 18:27*/
public class MyRunnable implements Runnable {public void run() {// 线程执行的代码System.out.println("线程执行啦!");}
}public class ThreadDemo {public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);thread.start();System.out.println("主线程执行啦!");}
}
在上述代码中,MyThread类继承了Thread类,并重写了run方法。在ThreadDemo 类中,创建了一个MyThread实例,并调用start方法启动线程。
执行结果肯定如下所示:
还不够熟练地同学,这里也可以再多敲敲试一下。
应用场景案例
这里我们来谈谈,多线程可以应用于的各种场景,包括并发访问共享资源、提高程序性能、实现异步任务等。以下是几个常见的应用场景案例:
- 并发访问共享资源:多个线程同时访问同一个共享资源时,会出现竞态条件。使用多线程可以解决并发访问共享资源的问题,提高程序的执行效率。
- 提高程序性能:将耗时的任务拆分成多个子任务,用多线程同时执行,可以显著提高程序的运行速度。
- 实现异步任务:多线程可以在后台执行耗时的操作,让程序能够同时响应用户的输入和其他事件。
优缺点分析
多线程编程有很多优点,同时也存在一些缺点,毕竟任何事物都要辩证看待。以下是对多线程编程的优缺点分析:
优点:
- 提高程序的执行效率,充分利用多核处理器的计算能力。
- 改善用户体验,使程序能够同时响应用户的输入和其他事件。
- 实现复杂的并发控制,提高程序的可扩展性和可维护性。
缺点:
- 多线程编程更加复杂,需要考虑线程安全、竞态条件等问题。
- 线程间的通信和同步开销较大,可能引入死锁和性能损失等问题。
- 调试和问题排查更加困难,因为多线程程序的执行顺序不确定。
类代码方法介绍
在Java中,线程类常用的方法有以下几种:
- start():启动线程,并调用线程的run方法。
- sleep():使线程进入休眠状态,暂停执行一段时间。
- join():等待线程执行完毕,再继续执行当前线程。
- interrupt():中断线程的执行。
熟悉上述方法后,我们就要来实战演示了。
Java代码测试用例
以下是一个简单的Java多线程测试用例,用于计算从1到10的累加和,代码演示如下,仅供参考:
package com.example.javase.ms.threadDemo.day2;/*** @Author ms* @Date 2024-04-12 19:09*/
public class MyThread extends Thread {private static int sum = 0;public void run() {for (int i = 1; i <= 10; i++) {sum += i;}}public static void main(String[] args) throws InterruptedException {MyThread thread1 = new MyThread();MyThread thread2 = new MyThread();thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("Sum is: " + sum);}
}
在上述代码中,MyThread类继承了Thread类,并重写了run方法。在主线程中,创建了两个MyThread实例,并分别启动两个线程。最后,使用join方法等待两个线程执行完毕,并打印累加和。
测试结果展示:
当程序运行时,它将创建两个线程,每个线程都会独立地计算从1到10的和。由于线程的执行是由操作系统的线程调度器控制的,所以两个线程完成计算的顺序是不确定的。但是,由于join()
方法的使用,我们可以确保在主线程打印sum
的值之前,两个线程都已经完成了它们的计算。结果展示如下:
其实上述代码,从执行结果上来看,不知道大家有没有发现问题!可以评论区交流下,虽然我下文也会给出对应的代码优化。
测试代码解析:
根据如上代码作出解析,以便于同学们更好的理解,分析如下:
如上测试用例展示了一个简单的多线程示例,其中创建了两个线程,每个线程都执行一个for
循环来计算从1到10的整数和。这个示例使用了Thread
类来创建和管理线程。
-
MyThread
类继承了Thread
类,并重写了run()
方法。在run()
方法中,通过一个循环计算从1到10的整数和,并将结果累加到静态变量sum
中。 -
在
main
方法中,创建了两个MyThread
对象:thread1
和thread2
,并且分别启动了这两个线程。 -
thread1.join();
和thread2.join();
这两行代码使得主线程等待thread1
和thread2
完成执行。join()
方法确保了在主线程继续执行之前,当前线程(在这个例子中是thread1
和thread2
)已经终止。 -
最后,一旦两个线程都完成了它们的计算,主线程将打印出静态变量
sum
的值。
注意事项
- 由于
sum
是一个静态变量,它在所有MyThread
实例之间共享。这意味着两个线程都会访问和修改同一个sum
变量,这可能导致线程安全问题,如竞态条件。这里就是我上述所提到的问题。 - 在这个特定的例子中,由于每次只有一个线程在执行
run()
方法,所以不会出现竞态条件。但是,如果sum
的更新是在多个线程中并发进行的,那么就需要使用同步机制来确保线程安全。
改进建议
那么如何避免潜在的线程安全问题呢?其实很简单,这里我们可以使用synchronized
关键字来同步对sum
的访问。优化代码如下:
/*** @Author ms* @Date 2024-04-12 19:14*/
public class MyThread_update extends Thread {private static final Object lock = new Object();private static int sum = 0;public void run() {for (int i = 1; i <= 10; i++) {synchronized (lock) {sum += i;}}}public static void main(String[] args) throws InterruptedException {MyThread_update thread1 = new MyThread_update();MyThread_update thread2 = new MyThread_update();thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("Sum is: " + sum);}
}
在这个改进的版本中,我们使用了一个对象lock
作为同步锁。在每次更新sum
变量时,我们都会获取这个锁,这样可以确保在同一时间只有一个线程能够执行更新操作。这有助于防止多个线程同时写入sum
变量,从而避免竞态条件。
然后,我们再来执行测试一下,结果展示如下:
全文小结
本文介绍了Java多线程的生命周期,包括线程状态的转换和对应的方法调用。通过源代码解析、应用场景案例和优缺点分析等方式,帮助读者更好地理解和应用线程的生命周期。同时,通过Java代码测试用例演示了多线程的具体应用。
总结
了解和掌握Java多线程的生命周期对于编写高效且可靠的多线程程序至关重要。本文通过介绍线程的状态转换、方法调用和具体应用场景,为读者提供了丰富的知识和实践经验。通过合理地应用多线程技术,开发人员可以提高程序的执行效率,改善用户体验,并解决复杂的并发控制问题。
… …
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
… …
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
相关文章:

Java零基础之多线程篇:线程生命周期
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一…...

技术差异,应用场景;虚拟机可以当作云服务器吗
虚拟机和云服务器是现在市面上常见的两种计算资源提供方式,很多人把这两者看成可以相互转换或者替代的物品,实则不然,这两种资源提供方式有许多相似之处,但是也有不少区别,一篇文章教你识别两者的技术差异,…...

Qt Quick 教程(一)
文章目录 1.Qt Quick2.QML3.Day01 案例main.qml退出按钮,基于上面代码添加 4.使用Qt Design StudioQt Design Studio简介Qt Design Studio工具使用版本信息 1.Qt Quick Qt Quick 是一种现代的用户界面技术,将声明性用户界面设计和命令性编程逻辑分开。 …...
react钩子函数用法(useCallback、useMemo)
useMemo import { useMemo } from react; function MyComponent({ a, b }) { const memoizedValue useMemo(() > { // 进行一些昂贵的计算 return a b; }, [a, b]); // 当 a 或 b 发生变化时,memoizedValue 将被重新计算 return <div>{memoizedVa…...

linux配置Vnc Server给Windows连接
1. linux 安装必要vnc server和桌面组件 sudo apt -y install tightvncserversudo apt install xfce4 xfce4-goodies2. linux 配置vncserver密码 #bash vncserver参考: https://cn.linux-console.net/?p21846#google_vignette 3. 将启动桌面命令写入.vnc/xstartup # .vnc/x…...
Android中的KeyEvent详解
介绍 在Android中,KeyEvent 是用来表示按键事件的类,可根据对应的事件来处理按键输入,具体包含了关于按键事件的信息,例如按键的代码、动作(按下或释放)以及事件的时间戳,KeyEvent 对象通常在用…...

移植案例与原理 - HDF驱动框架-驱动配置(2)
1.2.7 节点复制 节点复制可以实现在节点定义时从另一个节点先复制内容,用于定义内容相似的节点。语法如下,表示在定义"node"节点时将另一个节点"source_node"的属性复制过来。 node : source_node示例如下,编译后bar节点…...

年终奖发放没几天,提离职领导指责我不厚道,我该怎么办?
“年终奖都发了,你还跳槽?太不厚道了吧!” “拿完年终奖就走人,这不是典型的‘骑驴找马’吗?” 每到岁末年初,关于“拿到年终奖后是否应该立即辞职”的话题总会引发热议。支持者认为,这是个人…...
多处理系统结构
目录 统一内存访问(UMA)多处理器系统结构 优点 缺点 应用场景 UMA 结构的架构示例 解决方案和改进 非统一内存访问(NUMA)多处理系统结构 概述 NUMA的优点 NUMA的缺点 NUMA系统的工作原理 NUMA优化策略 结论 现代计算…...

创建进程的常用方式
自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中有多个模块可以创建进程,比较常用的有os.fork()函数、multiprocessing模块和Pool进程池。由于os.fork()函数只适用于Unix/Linu…...

李宏毅2023机器学习作业HW06解析和代码分享
ML2023Spring - HW6 相关信息: 课程主页 课程视频 Sample code HW06 视频 HW06 PDF 个人完整代码分享: GitHub | Gitee | GitCode P.S. HW06 是在 Judgeboi 上提交的,出于学习目的这里会自定义两个度量的函数,不用深究,遵循 Sugge…...
专业技能篇--算法
文章目录 前言经典算法思想总结一、贪心算法二、动态规划三、回溯算法四、分治算法 前言 这篇简单理解一些常见的算法。如果面试的时候问到相关的算法,能够应付一二。 经典算法思想总结 一、贪心算法 思想:贪心算法是一种在每一步选择中都采取在当前状…...
Vue中CSS动态样式绑定
Vue中CSS动态样式绑定与注意事项_vue css动态绑定-CSDN博客 在 Vue 中,你不能直接在 CSS 中直接绑定 data 中的数据,因为 CSS 不是响应式的。但是,有几种方法可以实现根据 Vue 实例中的数据来动态地改变样式: 内联样式绑定&…...

【漏洞复现】契约锁电子签章平台 add 远程命令执行漏洞(XVE-2023-23720)
0x01 产品简介 契约锁电子签章平台是上海亘岩网络科技有限公司推出的一套数字签章解决方案。契约锁为中大型组织提供“数字身份、电子签章、印章管控以及数据存证服务”于一体的数字可信基础解决方案,可无缝集成各类系统,让其具有电子化签署的能力,实现组织全程数字化办公。通…...
计算机专业是否仍是“万金油”?
身份角度一:一名曾经的计算机专业学生 随着高考的结束,我站在了人生的分岔路口,面临着大学专业的选择。在众多的选择中,计算机专业一直是我深思熟虑后的一个重要选项。然而,我并不清楚自己是否真的适合这个专业&…...
Spring 启动顺序
在 Spring 框架中,应用启动过程涉及多个步骤和组件的初始化。理解 Spring 启动顺序不仅有助于优化应用性能,还能帮助开发人员排查启动过程中可能出现的问题。本文将详细介绍 Spring 启动过程中的关键步骤和顺序。 1. Spring 启动过程概述 Spring 应用的…...
2024.06.19 刷题日记
41. 缺失的第一个正数 这个题目的通过率很低,是一道难题,类似于脑筋急转弯,确实不好想。实际上,对于一个长度为 N 的数组,其中没有出现的最小正整数只能在 [1,N1] 中。 这个结论并不好想,举个例子&#x…...
linux系统中,pwd获取当前路径,dirname获取上一层路径;不使用 ../获取上一层路径
在实际项目中,我们通常可以使用 pwd 来获取当前路径,但是如果需要获取上一层路径,有不想使用 …/ 的方式,可以尝试使用 dirname指令 测试shell脚本 #!/bin/bash# 获取当前路径 CURRENT_PATH$PWD echo "CURRENT_PATH$CURREN…...

DeepSpeed Monitoring Comm. Logging
Monitoring 支持多种后端:Tensorboard、WandB、Comet、CSV文件; TensorBoard例子: 自动监控:DeepSpeed自动把重要metric记录下来。只需在配置文件里enable相应的看板后端即可: {"tensorboard": {"enabl…...

关于INCA的几个实用功能
01--VUI窗口设计 这个可以按照自己的想法设计INCA观测或标定窗口 首先进入到INCA的环境内,点击实验→加载VUI窗口 选择空的窗口 打开后如下所示: 点击UI开发模式,如下图 如下: 添加标定量、观测量、示波器 窗口的大小需要在开发…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...