JavaEE初阶——多线程(二)

在这里插入图片描述

T04BF

👋专栏: 算法|JAVA|MySQL|C语言

🫵 小比特 大梦想

此篇文章延续上一篇文章,与大家分享Thread常见的方法以及线程的状态相关知识
其他内容我们下一篇再见!
如果有错误或不足请您指出!!!

目录

  • 3.Thread类及常见方法
    • 3.1Thread常见的构造方法
    • 3.2Thread常见的几个属性
  • 4.中断一个线程
    • 4.1自己实现控制线程结束
    • 4.2调用Thread提供的interrupt方法
  • 5 .等待一个线程
  • 6.获取当前线程的引用
  • 7.线程的状态
    • 7.1 new
    • 7.2 terminated
    • 7.3 Runnable
    • 7.4阻塞
    • 7.5查看当前线程的状态

3.Thread类及常见方法

3.1Thread常见的构造方法

在这里插入图片描述
(1)String name,就是在创建线程的时候,给线程起个名字,实际上是否有名字对线程本身没有任何影响,即使你不起名字,线程也会有默认的名字:Thread-0,Thread-1…,只不过起了名字后,当进程执行的过程中,可以通过jconsole / idea看到不同线程的名字,出现问题的时候,更加直观的把问题线程和代码关联起来,方便调试

public class Test1 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{while(true){System.out.println("hello t");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}},"自定义线程");t.start();while(true){System.out.println("hello main");Thread.sleep(1000);}}
}

在这里插入图片描述
(2)对于ThreadGroup,在开发中很少见到,有的时候,希望把多个线程进程分组,分组之后,就可以针对不同的分组进行批量控制
但是这种写法目前在实际开发中更多的是被线程池取代了

3.2Thread常见的几个属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()

(1)id 这里的id和pcb里面的pid是不一样的,这里的id是jvm自己搞的一套id体系,而我们通过java代码是不能获取到pcb里面的id的

(2)优先级
实际上虽然iava而提供了修改优先级的接口,但是即使你修改了优先级,现象也是不明显的,因为你修改了优先级是一回事,系统调度又是一回事,这里你修改了优先级只能说是一种"建议",具体还是以系统为主

而不仅是在java,即使你通过c去调用系统原生的修改优先级的api,效果也是不明显的,本质上还是因为调度这个事情,操作系统就一堂言了,程序员很难干预到

(3)前台线程和后台线程
对于前台线程,这样的线程不结束的话,java进程是一定不会结束的
对于后台线程,这样的线程即使继续执行,也是无法阻止java进程结束的

前台线程是可以有多个的,但是是有是当最后一个前台线程结束后,进程才算真正结束

在java中,main就是前台线程,而我们自己创建的线程默认也是前台线程,至于其他jvm创建的线程就是后台线程了,比如GC,GC是要周期性持续性的运行的,如果这样的线程设置为前台线程,那么进程就再也结束不了了

在这里插入图片描述
如图所示,main线程和t线程都是前台线程的时候,即使main结束了,进程也没有结束,必须等到t线程结束,进程才结束

在java中,我们可以通过setDaemon来将线程设置为后台线程
在这里插入图片描述
此时由于只有main线程是前台线程,那么一旦前台线程结束后,进程也就结束了

注意:关于线程属性的所有设置都要放在start之前,如果在start之后设置,那就来不及了
在这里插入图片描述

(5)是否存活
指的是在系统中的pcb(线程)是否存活
值得注意的是,线程的生命周期和java中Thread对象的生命周期不一定完全一样的
我们来对比一下下面的两段代码

public class Demo5 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {});t.start();Thread.sleep(1000);}
}

此时由于T线程里面没有做什么事情,因此操作系统内核里面对应的pcb一下子就销毁了,但是由于主线程调用了sleep,在sleep结束之前,Thread对象是不会销毁的

public class Demo5 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();t = null;}
}

此时在t线程结束之前,t线程指向的对象就要被GC回收了

因此,对于线程的生命周期和线程对应对象的是生命周期是不一样的,不能说谁长谁短,那么我们就可以利用isAlive来判断系统中的线程是否还存在

4.中断一个线程

中断线程,在java中也只是"提醒、建议"真正要不要终止,还是要线程本身来决定的
即假设t线程正在执行,其他线程只能是提醒一下t线程是否要终止,t收到这样的提醒后,也是靠自己决定要不要终止

4.1自己实现控制线程结束

private static boolean isRunning = true;
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while(isRunning){System.out.println("t线程运行");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println("t线程结束了");});t.start();//3s后,让t线程结束Thread.sleep(3000);System.out.println("控制t线程结束");isRunning = false;
}

但是假设这里t线程的sleep时间是10s,此时main线程是无法让t线程即使终止掉的

4.2调用Thread提供的interrupt方法

我们刚刚是自己定义的一个boolean变量,实际上Thread里面内置了一个,使用内置的标志位,功能更加强大
在这里插入图片描述
interrupt(): 这是一个实例方法,用于中断线程。当调用某个线程的 interrupt() 方法时,会给该线程设置一个中断标志,表示该线程已被请求中断。如果线程处于阻塞状态(如等待、睡眠或在输入输出操作中被阻塞),它会收到一个 InterruptedException 异常,以此来响应中断请求。在其他情况下,需要检查线程的中断状态,并采取适当的行动来响应中断请求。

interrupted(): 这是一个静态方法,用于检查当前线程是否被中断,并且会清除线程的中断状态。如果调用线程的 interrupted() 方法返回 true,则表示该线程之前被中断过,并且清除了中断状态;如果返回 false,则表示该线程之前未被中断过。通常,这个方法用于检查当前线程是否被中断,并在必要时做出相应的处理。

isInterrupted(): 这是一个实例方法,用于检查线程是否被中断,但不清除中断状态。调用线程的 isInterrupted() 方法返回 true 表示该线程被中断,返回 false 表示未被中断。通常,这个方法用于检查其他线程的中断状态,而不影响当前线程的中断状态。
在这里插入图片描述
当一个线程正在sleep的时候被中断,此时就会抛出InterruptedException异常,即立即唤醒线程,不会再等待了

但是如果我们不采用抛出异常的方法:
在这里插入图片描述
怎么t线程还会继续执行???
实际上是由于sleep,如果调用interrupt方法后,线程没有sleep,确实是直接修改标志位就完了
但是如果正在sleep,那么就会立即唤醒sleep,但sleep在被唤醒的同时,也会清除刚刚的标志位!!!
之所以要清除标志位,实际上也就是要将控制权交给程序员自己,当前代码是要继续执行?还是直接结束,程序员就可以通过代码来决定了
在这里插入图片描述

5 .等待一个线程

在操作系统中.多个线程之间的调度顺序是随机的(抢占式执行),但是我们往往希望线程的执行顺序是稳定的,因此我们希望在随机的体系上,让结果变得不那么随机
具体来说,一个线程数什么时候调度是不确定的,多个线程谁先开始谁先结束是不确定的
我们通过线程的等待,就是要能够确线程结束的先后顺序
在这里插入图片描述
如果不加join方法,那么main线程和t线程谁先结束是不确定的
但是在main线程里面调用t.join,就是要让main线程去等待t线程,也就是t线程结束后,main线程才继续执行下面的逻辑
此时就确保了main线程一定是后结束的那一个线程

注意:此时main线程调用t.join方法就会有几种情况
(1)如果此时t线程已经结束,那么join方法就立即返回,不会阻塞main线程
(2)如果t线程还没结束,那就一直等待到t线程结束
(3)如果t线程还没开始,也是直接返回

实际上join也提供了带超时的版本
在这里插入图片描述
只带一个参数的join,代表等待N ms

带两个参数则精确到毫秒和纳秒

(但是实际上纳秒这个级别的时间,对于主流系统来说,都是太精细了.像windows / linus这样的系统,无法精确到ns级别的时间 甚至到了ms级别都有可能出差错.而且达到ns这种级别的系统开销太大了)

传入的时间则代表最长的等待时间,比如写了10ms,如果10ms还没到,t线程已经结束了,那么就直接返回

如果10ms到了,t线程还没结束,那么就不等了,继续往下走

这种场景应用还是非常广泛的

假如A中的主线程创建t线程,t线程给B发送请求,紧接着A就让主线程t.join等待t线程结束(获取到B响应)

如果B挂了.此时如果是使用死等的策略,就会使A中的主线程卡住了,无法再继续执行后面逻辑了

这种情况就需要制定好超时时间,超过时间就不等了,继续做该做的事情
在这里插入图片描述

6.获取当前线程的引用

public static Thread currentThread();

返回的是当前线程对象的引用

7.线程的状态

我们在上一章节谈到的进程的状态实际上是线程的状态或者叫做pcb的状态
在Java中,对线程的状态大体是分成6中不同的状态

7.1 new

表示Thread对象已经有了,但是还没有start,即操作系统内核的pcb还没创建

7.2 terminated

表示线程已经终止了,即内核中的线程已经销毁了,但是Thread对象还在

7.3 Runnable

分成两种
(1)指的是当前线程正在cpu上执行
(2)指的是这个线程虽然没有在cpu上执行,但随时可以调度到cpu上执行

7.4阻塞

(1)waiting 死等进入的阻塞
(2)timed_waiting 带有超时版本的阻塞(sleep属于其中的一种)
(2)blocked 进行锁竞争时候产生的阻塞(后面会谈到)

7.5查看当前线程的状态

(1)getState
在这里插入图片描述
(2)jconsole
在这里插入图片描述

感谢您的访问!!期待您的关注!!!

在这里插入图片描述

T04BF

🫵 小比特 大梦想

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

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

相关文章

Ubuntu下载内核源代码

使用apt-get获取源代码,下载tar文件 $ apt-get install linux-source可以把tar文件复制到想要的目录,然后进行解压。 $ cp /usr/src/linux-source-5.15.0.tar.bz2 your_path $ cd your_path $ tar xjf linux-source-5.15.0.tar.bz2也可以去tar文件的目…

STM32H743VIT6使用STM32CubeMX通过I2S驱动WM8978(2)

接前一篇文章:STM32H743VIT6使用STM32CubeMX通过I2S驱动WM8978(1) 本文参考以下文章及视频: STM32CbueIDE Audio播放音频 WM8978 I2S_stm32 cube配置i2s录音和播放-CSDN博客 STM32第二十二课(I2S,HAL&am…

CLIP大模型图文检索——原理解读及代码实现

一. 核心思想 通过自然语言处理获得的监督信号可用于训练迁移效果出色的视觉模型。本论文的作者团队构建了一个庞大的图像文本配对数据集,其中包含400 million个图片文本的配对。利用最大规模的ViT-large模型,他们提出了CLIP(Contrastive La…

两个链表的交集(力扣349)

题目如下: 给定两个数组 nums1 和 nums2 ,返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1: 输入:nums1 [1,2,2,1], nums2 [2,2] 输出:[2]示例 2:…

go 利用channel实现定时任务

package mainimport ("fmt""net/http""time" )func main() {// 创建一个定时器,每隔1秒钟执行一次ticker : time.NewTicker(1 * time.Second)done : make(chan bool)//设置3s超时,避免请求时间过长client : http.Client{T…

Postgresql获取指定时间前的时间

1、获取指定时间前12小时数据 SELECT* FROMdispatch_team_real WHEREto_timestamp( start_time, YYYY-MM-DD HH24:MI:SS ) ( to_timestamp( 2023-09-17 06:00:00, YYYY-MM-DD HH24:MI:SS ) - INTERVAL 12 HOUR ) AND to_timestamp( end_time, YYYY-MM-DD HH24:MI:SS ) ( t…

机器学习和深度学习 -- 李宏毅(笔记与个人理解)Day 13

Day13 Error surface is rugged…… Tips for training :Adaptive Learning Rate critical point is not the difficult Root mean Square --used in Adagrad 这里为啥是前面的g的和而不是直接只除以当前呢? 这种方法的目的是防止学习率在训练过程中快速衰减。如果只用当前的…

自然语言处理NLP关键知识点

大家好,在人工智能出现之前,机器智能处理结构化的数据,例如 Excel 里的数据。但是网络中大部分的数据都是非结构化的,例如文章、图片、音频、视频等。在非结构数据中,文本的数量是最多的,他虽然没有图片和视…

信息系统项目管理师——第27章管理科学基础知识

1 最大流量问题[简单] 百度百科:最大流问题,一种组合最优化问题,就是要讨论如何充分利用装置的能力,使得运输的流量最大,以取得最好的效果。 教材P869:在起点和终点之间可能存在多条运输路径,总的最大流量就是求出各…

智能EDM邮件营销推广工具哪个好?

有效且精准的客户沟通已经成为企业成功的关键要素之一,云衔科技以其尖端的智能EDM邮件营销系统解决方案脱颖而出,为全球各行业的企业提供了一个强有力的竞争优势和业绩增长引擎。 云衔科技深谙市场营销的艺术与科学,凭借多年积累的专业技术研…

C#:判断一个数是不是水仙花数

任务描述 本关任务:编写一个程序,判断从键盘输入的数是不是水仙花数。 水仙花数是指一个3位数字,它各位数字的3次幂之和等于它本身。如153是一个水仙花数,因为: 1531 3 5 3 3 3 相关知识 为了完成本关任务&am…

SPI 机制

一、简述 本文介绍 SPI 机制。 二、什么是 SPI 机制 SPI(Service Provider Interface)机制是 Java 编程语言中的一种机制,用于实现组件之间的解耦和扩展。SPI 允许开发者编写服务接口(Service Interface)&#xff0…

Python基础教程

随着科技的快速发展,编程已成为一项重要的技能。在众多编程语言中,Python因其简洁、易读、强大的功能库而备受青睐。无论你是编程新手,还是希望了解Python的开发者,本文都将为你提供一个Python基础教程,带你走进Python…

计算机网络 路由器基本配置

一、实验内容 1、按照下表配置好PC机IP地址和路由器端口IP地址 2、配置好路由器特权密文密码“abcd+两位班内序号”和远程登录密码“star” 3、验证测试 a.验证各个接口的IP地址是否正确配置和开启 b.PC1 和 PC2 互ping c.验证PC1通过远程登陆到路由器上&#…

目前深圳嵌入式单片机就业环境如何?

深圳作为中国的科技创新中心之一,嵌入式行业的就业环境相对较好。我这里有一套嵌入式入门教程,不仅包含了详细的视频讲解,项目实战。如果你渴望学习嵌入式,不妨点个关注,给个评论222,私信22,我在…

docker 上达梦导入dump文件报错:本地编码:PG GBK,导入女件编码:PGGB18030

解决方案: 第一步进入达梦数据容器内部 docker exec -it fc316f88caff /bin/bash 第二步:在容器中 /opt/dmdbms/bin目录下 执行命令 cd /opt/dmdbms/bin./dimp USERIDSYSDBA/SYSDBA001 FILE/opt/dmdbms/ZFJG_LJ20240407.dmp SCHEMASZFJG_LJUSERIDSYSD…

Lua语法(三)——元表与元方法

参考链接: 系列链接: Lua语法(一) 系列链接: Lua语法(二)——闭包/日期和时间 系列链接: Lua语法(三)——元表与元方法 系列链接: Lua语法(四)——协程 系列链接: Lua语法(五)——垃圾回收 系列链接: Lua语法(六)——面相对象编程 元表与元方法目录 简介正文元表元方法表相关常…

linux安装

1、解压vm ware压缩包 2双击安装 3点击自定义硬件 4双击cd/dvd,给虚拟光驱里放虚拟光盘 5记得启动时链接勾上,勾上起点系统时 虚拟光驱才会一起启动 6点击确认即可! 开机 选择第一个 7进入图形化安装界面 8设置时区 9选择硬盘 10网络配置 开启以太网&am…

C语言进阶课程学习记录-数组指针和指针数组分析

C语言进阶课程学习记录-数组指针和指针数组分析 实验-数组指针的大小实验-指针数组小结 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 实验-数组指针的大小 #include <stdio.h>typedef int(AINT…

简述Java中synchronized关键字的底层工作原理

在Java中&#xff0c;synchronized 关键字是一个重要的同步机制&#xff0c;用于控制多线程对共享资源的访问&#xff0c;以防止并发问题。了解 synchronized 的底层工作原理&#xff0c;可以帮助我们更好地编写线程安全的代码。synchronized 关键字可以应用于方法或者代码块&a…