【JavaEE】——多线程(join阻塞,计算,引用,状态)

阿华代码,不是逆风,就是我疯,你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你!

目录

一:join等待线程结束

1:知识回顾

2:join的功能就是“阻塞等待”

3:谁调用谁等待

4:join和“优先级”区分

二:多线程运行计算

1:情景引入

2:多线程提升进程的运行效率

(1)代码分析

3:串行执行

三:获取线程的引用

1:Thread.currentThread():

2:创建线程方式影响this引用

3:代码举例如下

四:线程的状态

0:.getState()

1: NEW

2:TERMINATED

3:RUNNABLE

4:TIME_WAITING

5:WAITING

6:BLOCK


引入:通过上一篇文章的学习,我们知道可以通过用Thred的sleep方法,让main函数这个线程进行沉睡,进而达到,让其它线程先执行完毕,main函数在执行这种目的。但是如果不清楚其他线程何时结束,就不能使用sleep方法了

一:join等待线程结束

1:知识回顾

(1)多线程的调度是无序的(随机调度,抢占式执行)

(2)可以通过操作系统提供的一系列api来控制线程的执行顺序

2:join的功能就是“阻塞等待”

如果t1这个线程还在运行,main函数就必须等着,这就是“阻塞等待”。(可以理解成插队,我join到你前面了,一定是我先买到票走人)(阅读以下代码加深理解)

3:谁调用谁等待

因为实在main函数中,t1join进去的,所以main函数等待。如果现在有t1,t2,两个线程都join了呢?——t1 , t2 并发执行,随机调度,两者都执行完毕了,main函数才能执行

4:join和“优先级”区分

join不是确定“执行顺序”而是确定“结束顺序”,本质是让调用操作系统的api进行控制,让main函数放弃去“调度器”中调度。

package thread;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-20* Time: 20:34*/
public class ThreadDemon14 {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{for (int i = 0; i < 5; i++) {System.out.println("t1线程正在运行");try {Thread.sleep(500);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.start();t1.join();System.out.println("这里是main函数线程,我需要等待t1线程执行完毕,才能进行打印");}
}

二:多线程运行计算

1:情景引入

问题:我们用单线程和多线程去计算前1_0000_0000个数字之和,看两者速度差多少

2:多线程提升进程的运行效率

(1)代码分析

下面第一个代码——兵分三路:①main,②算1~5000_0000 ,③算5000_0001~1_0000_0000。本质上来说是  (并发执行=并行+并发) ②③在不同的核心上(并行) ,②③同时运行(并发)

不懂得可以看我前面写过的文章哦!有举例子。

package thread;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-19* Time: 14:13*/
public class ThreadDemon15 {private static long result = 0;public static void main(String[] args) throws InterruptedException {//用多线程去计算前多少个数字之和Thread thread = new Thread(()->{long tem = 0;for (long i = 0; i < 5000_0000L; i++) {tem += i ;}result += tem ;});Thread thread2 = new Thread(()->{//thread.join();//又变成了串行执行了,并非并发执行long tem = 0;for (long i = 5000_0001 ; i < 1_0000_0000L ; i++) {tem += i;}result += tem;});thread.start();//创建一个新的线程,新的线程跟之前的线程是"并发执行"的关系thread2.start();long beg = System.currentTimeMillis();//记录开始时间//main函数线程阻塞,等待thread线程运行thread.join();thread2.join();//确保thread进程执行完毕在执行main函数long end = System.currentTimeMillis();//记录结束时间System.out.println("双线程的计算结果是:" + result);System.out.println("双线程用到的时间是:" + (end - beg) );}
}

package thread;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-20* Time: 21:03*/
public class ThreadDemon15_2 {private static long result = 0;public static void main(String[] args) throws InterruptedException {//用多线程去计算前多少个数字之和Thread thread = new Thread(()->{long tem = 0;for (long i = 0; i < 1_0000_0000L; i++) {tem += i ;}result += tem ;});thread.start();//创建一个新的线程,新的线程跟之前的线程是"并发执行"的关系long beg = System.currentTimeMillis();//记录开始时间//main函数线程阻塞,等待thread线程运行thread.join();long end = System.currentTimeMillis();//记录结束时间System.out.println("单线程的计算结果是:" + result);System.out.println("单线程用到的时间是:" + (end - beg) );}
}

3:串行执行

有没有办法让第一个线程结束,在进行第二个线程,最后执行main函数

三:获取线程的引用

1:Thread.currentThread():

获取到当前线程的引用(Thread引用)

2:创建线程方式影响this引用

如果继承的是Thread类,那么可以用this拿到线程的引用

如果是Runnable或者lambda的方式创建线程,this不能指向Thread对象了,那么此时this就不可以用了,就只能使用Thread.currentThread。

3:代码举例如下

package thread;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-19* Time: 16:18*/
class MyThread5 extends Thread{@Overridepublic void run() {System.out.println(this.getId() + "," + this.getName());}
}
public class ThreadDemon16 {public static void main(String[] args) throws InterruptedException {/** t1,t2 的先后顺序是不确定的,线程的随机调度*/Thread t1 = new MyThread5();Thread t2 = new MyThread5();t1.start();t2.start();Thread.sleep(1000);System.out.println(t1.getId() + t1.getName());System.out.println(t2.getId() + t2.getName());}}

package thread;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-19* Time: 16:27*/
public class ThreadDemon17 {/** 使用lambda表达式和Runnable接口写法,就不能用this了*lambda中没有指向任何对象,this没法用* Runnable写法则是this指向的是Runnable* 所以只能用.currentThread这个方法来获取当前*/public static void main(String[] args) {Thread t1 = new Thread(()->{Thread t = Thread.currentThread();System.out.println(t.getId()+t.getName());});Thread t2 = new Thread(()->{Thread t = Thread.currentThread();System.out.println(t.getId()+t.getName());});t1.start();t2.start();}}

四:线程的状态

通过之前的学习,我们知道线程有就绪和阻塞两种状态。下面我们进行更深入的学习

0:.getState()

获取线程的状态

1: NEW

创建了Thread对象,但是还没有调用start方法,线程还没有运行起来

2:TERMINATED

terminated终止状态,一个线程已经执行完毕,但是Thread对象还存在,

3:RUNNABLE

runnable状态,线程正在cpu上运行,或者准备就绪,随时可以上cpu运行

4:TIME_WAITING

time_waiting状态, 多为sleep和join引起的带有一定时间的阻塞等待

5:WAITING

waiting状态,(线程死等),多为wait和join引起

6:BLOCK

block状态,由锁竞争引起的阻塞

/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-19* Time: 16:58*/
public class ThreadDemon18 {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{for (int i = 0; i < 3; i++) {System.out.println("线程正在运行");try {Thread.sleep(5000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});System.out.println("t1为NEW状态:"+t1.getState());t1.start();//开始执行线程System.out.println("t1是RUNNABLE状态" + t1.getState());t1.join();//main等待t1线程执行完毕         //想要获取WAITING状态把这一行屏蔽掉Thread.sleep(500);//这里是确保让下一句不要那么快执行,正好让 Thread在sleep(1000)的期间获取状态System.out.println("t1是TERMINATED状态"+t1.getState());}
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

tcp、udp通信调试工具Socket Tool

tcp、udp通信调试工具Socket Tool ]

【Unity设计模式】Unity MVC/MVP架构介绍,及MVC/MVP框架的简单应用

什么是MVC&#xff1f; MVC自1982年被设计出来&#xff0c;至今都有着很大比重的使用率&#xff0c;特别是目前软件及游戏迭代如此之快的情况下。高效的增删功能&#xff0c;低耦合又小巧灵活的框架MVC&#xff0c;深受广大ProgramDesigner的喜爱。 MVC框架相信大部分程序员&…

医院伤员小程序点餐———未来之窗行业应用跨平台架构

一、读取服务器医院信息 var 未来之窗人工智-商家信息-医院职工 {//2024-09-22 cyber_getMerchant_CardUser_V20240922: function(appikkey,merchant_id,store_id,ecogen_sponsor_appid,openid,frommsg,wlzc_callback) {//2023-7-6 里程碑var wlzcapi"加入url";wx.re…

Rust 运算符快速了解

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust编程与项目实战_夏天又到了的博客-CSDN博客 4.1 运 算 符 前面已经学习了变量和常量&#xff0c;本节开始对它们进行操作&am…

深度学习02-pytorch-08-自动微分模块

​​​​​​​ 其实自动微分模块&#xff0c;就是求相当于机器学习中的线性回归损失函数的导数。就是求梯度。 反向传播的目的&#xff1a; 更新参数&#xff0c; 所以会使用到自动微分模块。 神经网络传输的数据都是 float32 类型。 案例1: 代码功能概述&#xff1a; 该…

分页插件、代码生成器

01-分页插件、代码生成器 分页插件使用 首先在pom.xml文件中导入依赖 然后再mybatis-config.xml文件中写入插件 在测试类中写入方法 在mybatis.xml文件中设置plugins标签里的属性helperDialectkeyi自动检查当前数据库用的什么,不用设置也行,默认就设置了 分页插件里面属性详解…

【ranger编译报错】cloudera-manager-api-swaggerjar7.0.3 not found

cloudera-manager-api-swaggerjar7.0.3 not found 快捷导航 在开始解决问题之前&#xff0c;大家可以通过下面的导航快速找到相关资源啦&#xff01;&#x1f4a1;&#x1f447; 快捷导航链接地址备注相关文档-ambaribigtop自定义组件集成https://blog.csdn.net/TTBIGDATA/a…

【在Linux世界中追寻伟大的One Piece】IP分片和组装的具体过程

目录 1 -> IP分片和组装的具体过程 2 -> 分片与组装的过程 2.1 -> 分片 2.2 -> 组装 3 -> 分片与组装的示意图 3.1 -> 分片组装场景 1 -> IP分片和组装的具体过程 16位标识(id)&#xff1a;唯一的标识主机发送的报文。如果IP报文在数据链路层被分片…

利士策分享,华为三折叠手机:重塑未来科技生活的里程碑

利士策分享&#xff0c;华为三折叠手机&#xff1a;重塑未来科技生活的里程碑 在这个日新月异的科技时代&#xff0c;华为再次以惊人的创新力&#xff0c;引领我们迈向智能设备的全新纪元——华为三折叠手机&#xff0c; 不仅是技术的飞跃&#xff0c;更是对未来生活方式的一次…

【保奖思路】2024年华为杯研赛B题完整代码建模过程(后续会更新)

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片&#xff0c;那是获取资料的入口&#xff01; 点击链接加入【2024华为杯研赛资料汇总】&#xff1a;https://qm.qq.com/q/XzdIsvbiM0https://qm.qq.com/q/XzdIsvbiM0请根据附件WLAN网络实测训练集中所提供…

代理IP对于网络爬虫业务的重要性

在现代互联网业务中&#xff0c;网络爬虫已成为企业获取大量数据的重要工具。在这一过程中&#xff0c;代理IP发挥着至关重要的作用&#xff0c;特别是对于高频率的数据抓取任务&#xff0c;代理IP能够有效提升爬虫的成功率和安全性。 1. 绕过IP封禁 网站为了防止过度的爬虫行…

TC-RAG: 图灵完备的检索增强

1. 背景 大型语言模型在众多关键领域均已取得显著进展&#xff0c;并在各种下游任务中展现出卓越性能。 在医疗领域&#xff0c;这些模型尤显潜力&#xff0c;特别是在对责任感和可靠性要求极高的健康护理领域。这些模型通过全面的医学知识预训练&#xff0c;不仅能支持医生做…

Python语法(二)——函数

文章目录 函数语法格式函数参数链式调用嵌套调用函数递归变量作用域 函数 一段可以被重复使用的代码片段 求数列的和, 不使用函数 # 1.求1-100的和 sum 0 for i in range(1, 101):sum i print(fsum {sum})# 2.求300-400的和 sum 0 for i in range(300, 401):sum i print(…

NASA:ATLAS/ICESat-2 L3A 陆地和植被高度速览,第 6 版

目录 简介 参数 代码 引用 网址推荐 0代码在线构建地图应用 机器学习 ATLAS/ICESat-2 L3A 陆地和植被高度速览&#xff0c;第 6 版 ATLAS/ICESat-2 L3A Land and Vegetation Height Quick Look V006 简介 ATL08QL 是 ATL08 的快速查看版本。 一旦 ATL08 的最终文件可…

MongoDB在Linux系统中的安装与配置指南

在这篇文章中&#xff0c;我们将介绍如何在CentOS 7服务器上安装MongoDB&#xff0c;并通过DataX将数据从MongoDB迁移到MySQL数据库。这将包括MongoDB的安装、配置、数据准备以及使用DataX进行数据迁移的详细步骤。 MongoDB简介 MongoDB是一个高性能、开源、无模式的文档型数据…

[Java并发编程] synchronized(含与ReentrantLock的区别)

文章目录 1. synchronized与ReentrantLock的区别2. synchronized的作用3. synchronized的使用3.1 修饰实例方法&#xff0c;作用于当前实例&#xff0c;进入同步代码前需要先获取实例的锁3.2 修饰静态方法&#xff0c;作用于类的Class对象&#xff0c;进入修饰的静态方法前需要…

数据结构:二叉树(2)

ps&#xff1a;爆更第二期 前言 普通的树的实用价值比较小&#xff0c;将树更一步特殊化成二叉树&#xff0c;将获得更多的特殊性质。 例如搜索二叉树&#xff0c;红黑树等。 这篇博文主要介绍二叉树的基础知识&#xff0c;进阶版高级二叉树&#xff0c;后续会持续更新。 二叉…

RK3568平台(基础篇)万用表的使用

一.万用表的通断判断 万用表两个笔头的插法:黑笔头是插在COM的孔里面,红色笔头可以插在其他的三个孔里面,20A和mA分别用来测电流,另外一个孔可以用来测其他(电压 电阻)。 以下这个三角符号(像wifi一样的)可以用来测通断: 使用万用表的红笔和黑笔进行短接,这时候两端…

PAT (Advanced Level) Practice——1020Tree Traversals

链接&#xff1a; 1020 Tree Traversals - PAT (Advanced Level) Practice (pintia.cn) 题目大意&#xff1a; 首先给出一个整数n&#xff0c;表示序列一共有多少个数。接下来给出一棵树的后序遍历和中序遍历&#xff0c;根据后序遍历和中序遍历给出层序遍历。 题解&#x…

【技术调研】三维(7)-Unity基础笔记

安装 ​ 最好使用长期维护版本。 创建项目 ​ 略 窗口布局 Hierarchy:层级面板,展示当前打开的场景里面有哪些物体。 Scene:场景面板,显示当前场景的样子 Game:游戏面板,场景运行的时候的样子 Inspector:检视面板(或属性面板),查看一个游戏物体由哪些组件组成。 …