JavaEE初阶——多线程(二)

news2025/1/13 3:00:22

在这里插入图片描述

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.coloradmin.cn/o/1590663.html

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

相关文章

【小技巧】机器学习中可视化高维向量的两种方法PCA和t-SNE,以及其原理介绍和代码示例(附代码)

使用情景:比如说现在我有一批numpy的多维向量,比如说都是256维度的,X.shape(n, 256), 已知它们都是经过训练能够在256dim的超球面上实现分类或聚类的,现在我想把它们可视化出来看看各个簇在超球面上的分布是怎样的? 1…

C++的stack和queue类(三):适配所有容器的反向迭代器

目录 前言 list的反向迭代器 list.h文件 ReverseIterator.h文件 test.cpp文件 前言 迭代器按性质分类: 单向:forward_list双向:list随机:vector / deque 迭代器按功能分类: 正向反向const list的反向迭代器…

抽象工厂模式:深入探索面向对象设计的多样性

在软件开发中,正确地应用设计模式对于构建可扩展、可维护和高效的系统至关重要。抽象工厂模式作为创建型设计模式之一,提供了一个高层接口,用于创建一系列相关或依赖对象,而无需指定它们具体的类。本文将详细介绍抽象工厂模式的概…

【虚幻引擎】DTProjectSettings 蓝图获取基本项目配置插件使用说明 获取项目命名,项目版本,公司名,公司识别名,主页,联系方式

本插件可以使用蓝图获取到项目的一些基本配置,如获取:公司名、公司识别名、版权声明、描述、主页、许可条款、隐私政策、项目ID、项目命名、项目版本、支持联系方式、项目显示标题、项目调试标题信息、应保留窗口宽高比、使用无边框窗口、以VR启动、允许…

ASP.NET MVC企业级程序设计 (EF+MVP实现显示数据)

效果图 实现过程 1创建数据库 2创建项目文件 3创建控制器,右键添加,控制器 注意这里要写Home 创建成功 数据模型创建过程之前作品有具体过程 4创建视图,右键添加视图 5HomeController.cs代码 using System; using System.Collections.Gene…

JVM修炼之路【11】- 解决内存溢出、内存泄漏 以及相关案例

前面的10篇 都是基础的知识,包括类加载的过程 类加载的细节,jvm内存模型 垃圾回收 等等, 这一篇我们开始实战了解一下 各种疑难杂症:怎么监控 怎么发现 怎么解决 内存溢出 内存泄漏 这两个概念在垃圾回收器里面已经讲过了&#…

视频秒播优化实践

本文字数:2259字 预计阅读时间:10分钟 视频起播时间,即首帧时间,是视频类应用的一个重要核心指标,也是影响用户观看体验的核心因素之一。如果视频要加载很久才能开始播放,用户放弃播放甚至离开 App 的概率都…

React + three.js 实现人脸动捕与3D模型表情同步

系列文章目录 React 使用 three.js 加载 gltf 3D模型 | three.js 入门React three.js 3D模型骨骼绑定React three.js 3D模型面部表情控制React three.js 实现人脸动捕与3D模型表情同步 示例项目(github):https://github.com/couchette/simple-react-three-facia…

【Godot4自学手册】第三十六节圆形移动或扇形移动的铁球

在第三十四节我实现了来回无限滚动的伤害铁刺球,这一节我准备实现一个圆形移动或扇形移动,并带有链条的铁球。效果如下: 一、实现原理 绕一点做圆周运动,简单的说就是: 每一帧根据旋转的角度计算出下一个位置的坐标…

R语言绘图:绘制横向柱状图

代码主要实现&#xff1a; 对数据进行排序&#xff0c;并且相同分组的数据会有相同的颜色。最后&#xff0c;绘制横向柱状图。 # 加载ggplot2包 library(ggplot2)# 示例数据&#xff0c;假设有三列&#xff1a;Group, Variable, Value data <- data.frame(Group factor(c(…

植被参数光学遥感反演方法(Python)及遥感与生态模型数据同化算法

传统的地面实测方法能够得到比较准确的植被参数&#xff08;如叶面积指数、覆盖度、生物量、叶绿素、干物质、叶片含水量、FPAR等&#xff09;&#xff0c;但其获取信息有限&#xff0c;难以满足大范围提取植被参数的需求&#xff0c;尤其在异质地表区域。遥感技术的发展为植被…

【PythonCode】力扣Leetcode11~15题Python版

【PythonCode】力扣Leetcode11~15题Python版 前言 力扣Leetcode是一个集学习、刷题、竞赛等功能于一体的编程学习平台&#xff0c;很多计算机相关专业的学生、编程自学者、IT从业者在上面学习和刷题。 在Leetcode上刷题&#xff0c;可以选择各种主流的编程语言&#xff0c;如C…

316_C++_xml文件解析成map,可以放到表格上 + xml、xlsx文件互相解析

xml文件例如&#xff1a; <?xml version"1.0" encoding"UTF-8" standalone"yes"?> <TrTable> <tr id"0" label"TR_PB_CH" text"CH%2"/> <tr id"4" label"TR_PB_CHN"…

[BT]BUUCTF刷题第16天(4.12)

第16天 Web [MRCTF2020]Ezpop 打开网站就是一段泄露的源代码&#xff1a; <?php //flag is in flag.php //WTF IS THIS? //Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95 //And Crack…

Ollama、FastGPT大模型RAG结合使用案例

参考: https://ollama.com/download/linux https://doc.fastai.site/docs/intro/ https://blog.csdn.net/m0_71142057/article/details/136738997 https://doc.fastgpt.run/docs/development/custom-models/m3e/ Ollama作为后端大模型加载运行 FastGPT作为前端页面聊天集成RA…

Linux函数学习 select

1、Linux select 函数 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); nfds 最大文件fd 1 readfds 监听可读文件集合fd writefds 监听可写文件集合fd exceptfd 监听异常文件集…

[蓝桥杯] 岛屿个数(C语言)

提示&#xff1a; 橙色字体为需要注意部分&#xff0c;红色字体为难点部分&#xff0c;会在文章“重难点解答”部分精讲。 题目链接 蓝桥杯2023年第十四届省赛真题-岛屿个数 - C语言网 题目理解 这道题让我们求岛屿个数&#xff0c;那么我们就应该先弄懂&#xff0c;对于一…

R: 支持向量机(Support Vector Machine,简称SVM)

在数据科学和机器学习领域中&#xff0c;支持向量机&#xff08;Support Vector Machine&#xff0c;简称SVM&#xff09;是一种强大的监督学习算法&#xff0c;常用于分类和回归分析。它的优点之一是可以适用于复杂的数据集&#xff0c;并且在高维空间中表现良好。在本文中&am…

SpringBoot3 + Vue3 + Uniapp + uView + Elenment 实现动态二级分类以及二级分类的管理

SpringBoot3 Vue3 Uniapp uView Elenment 实现动态二级分类以及二级分类的管理 1. 效果展示1.1 前端显示效果1.2 后台管理一级分类1.3 后台管理二级分类 2. 后端代码2.1 GoodsCategoryController.java2.2.1 GoodsCategoryMapper.java2.2.2 GoodsCategorySonMapper.java2.3.…

蓝桥杯备赛(C/C++组)

README&#xff1a; 本笔记是自己的备考笔记&#xff0c;按照官网提纲进行复习&#xff01;适合有基础&#xff0c;复习用。 一、总考点 试题考查选手解决实际问题的能力&#xff0c;对于结果填空题&#xff0c;选手可以使用手算、软件、编程等方法解决&#xff0c;对于编程大…