【多线程】多线程(2):Thread方法,线程核心操作

news2024/9/30 9:48:53

 【Thread类其他的属性和方法】

给线程命名的方法,不起名字则默认叫做Thread-0,Thread-1……

【线程的属性】

ID,名称,状态,优先级:JVM自动分配,不能手动设置

状态:java中把线程的状态,分为阻塞与就绪

优先级:设置不同的优先级,会影响到系统的调度,这里的影响是基于“统计”规则的影响,直接肉眼观察,很难观察到结果

【前台,后台线程】

如果这个线程在执行过程中,能够阻止进程结束此时这个线程就是“前台线程”

如果这个线程在执行过程中,不能阻止进程结束(虽然线程在执行着,但是进程要结束了,此时这个线程也会随之被带走),这样的线程就是“后台线程”

【前台,后台线程】

如果这个线程在执行过程中,能够阻止进程结束,此时这个线程就是“前台线程”

如果这个线程在执行过程中,不能阻止进程结束(虽然线程在执行着,但是进程要结束了,此时这个线程也会随之被带走),这样的线程就是“后台线程”

举个例子:

上述过程中,主持人决定了这场宴席什么时候结束,当他宣布结束时,宴席就散了,若“我”是个只会干饭的小透明,无法决定宴席何时结束,在主持人还没有宣布宴席结束时溜了也不影响宴席继续

那么“我”就是“后台线程”

1.进程要结束,(前台线程要结束),后台线程无力阻止

2.后台线程先结束了,也不影响进程的结束

主持人就是“前台线程

1.前台线程宣布结束,此时进程就结束,后台线程也会随之结束

2.前台线程不结束,后台线程结束了也不影响

【守护线程】

public static void main(String[] args) {
        Thread t = new Thread(() ->{
            while(true){
                System.out.println("hello B");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();

//主线程不写循环,意味着主线程瞬间执行完了
}

主线程执行完了,但t还在执行,此时t默认是前台线程,只要它没有运行完,进程就不会停止

因此可以加上以下代码:t.setDaemon(true);

public static void main(String[] args) {
        Thread t = new Thread(() ->{
            while(true){
                System.out.println("hello B");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        t.setDaemon(true);
        t.start();

它可以把t设置为守护线程(后台线程),不再能阻止整个进程结束

【是否存活】

代码中创建的new Thread对象,生命周期和内核中的实际线程不一定一样,可能会出现Thread对象仍然存在,但内核中的线程不存在的情况

Thread t = new Thread(() ->{
            for(int i = 0;i < 3;i++){
                System.out.println("hello B");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        System.out.println(t.isAlive());//为false代表不存在,true代表存在,第一次在start之前调,肯定false
        t.start();
        System.out.println(t.isAlive());//第二次在start之后调,是true,说明内核中已经有了这个线程
        Thread.sleep(5000);
        System.out.println(t.isAlive());//这边sleep完的时候,线程早就结束了,所以是false

但由于线程的调度顺序是不确定的,如果两个线程都是sleep3000,此时时间一到,两个线程谁先执行谁后执行就不确定了

【线程的核心操作】

【创建线程start】

谈一谈start和run之间的差别(重点掌握):

run:描述了线程要执行的任务,是“线程的入口”

start:调用系统api,系统的api会真正在系统内核中创建线程,创建好新的线程后再单独执行run

其执行速度较快(创建线程比较轻量),一旦start执行完毕,就会兵分两路,新线程开始执行,调用start的线程(主线程)也会继续执行

此外,调用start,不一定非得是main线程调用,任何的线程都可以创建其他线程,如果系统资源充裕,就可以任意的创建线程

但要注意,一个Thread对象只能创建一个线程

【线程的终止】

线程A和线程B

B正在运行,A想让B结束,核心就是A想办法让B的run方法执行完毕,此时B就自然结束了,而不是说B的run执行一半时A直接把B强制结束了

Java中结束线程是一个“温柔”的过程,主要是担心B某个工作执行了一半就强制结束了,此时B对应的结果数据就是一个"半成品"(更希望是一个完整的过程)

 Thread t = new Thread(() ->{
            while(!isQuit){
                System.out.println("hello B");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t线程执行结束");
        });

        t.start();
        Thread.sleep(2000);
        //修改isQuit变量,就能影响到t线程的结束了
        System.out.println("main尝试终止t线程");
        isQuit = true;
    }

设置一个isQuit变量,就可以让线程提前结束

【通过获取线程的引用来终止线程】

Thread类中有一个成员,boolean类型的interrupted,初始情况下这个变量是false,一旦外面的线程调用了一个interrupted方法,就会设置上述标志位,变更为true

 Thread t = new Thread(() ->{
            Thread currentThread = Thread.currentThread();
            while(!currentThread.isInterrupted()){
                System.out.println("hello B");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t线程执行结束");
        });

        t.start();
        Thread.sleep(2000);
        t.interrupt();

currentThread是Thread类的静态方法,可以获取到调用这个方法的线程的实例,哪个线程调用,返回的引用就指向哪个线程的实例

但此处会产生报错

由于判定interrupted和执行打印这两个操作太快了,因此整个循环都是把时间花在了sleep上,main调用interrupt时,大概率t线程还处于sleep状态,此处interrupt不但能设置标志位,还能唤醒刚才的sleep操作

比如,此时sleep刚睡了100ms,还剩余900ms,此时interrupt被调用了会直接唤醒sleep,并且抛出InterruptedException异常,由于catc中默认代码再次抛出异常,再次抛出的异常没被catch,最终到了JVM,进程就直接异常终止了

Thread t = new Thread(() ->{
            Thread currentThread = Thread.currentThread();
            while(!currentThread.isInterrupted()){
                System.out.println("hello B");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("执行到catch操作");
                    break;
                }
            }
            System.out.println("t线程执行结束");
        });

        t.start();
        Thread.sleep(3000);
        t.interrupt();

sleep被唤醒后,会清空interrupted设置的标志位,导致无法结束循环,因此若确实想结束循环,结束线程,需要在catch中加上return/break

这样的设立方式是为了让线程有更多选择

1.若B线程想无视A,就直接catch中啥也不做,B线程中仍然会继续执行

sleep清除标志位就可以让B做出这样的选择,若不清除,B就会结束,无法让线程继续执行

2.若B想立即结束,就在catch中加上return/break,此时B会立即结束

3.若B想稍后再结束,就可以在catch中写上一些其他的逻辑,这些逻辑完成后,再进行return/break

这就给了程序员更多的操作空间

【总结】

1.interrupt方法能设置标志位,也能唤醒sleep等阻塞方法

2.sleep被唤醒后,能清空标志位

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

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

相关文章

速通数据结构与算法第六站 树堆

系列文章目录 速通数据结构与算法系列 1 速通数据结构与算法第一站 复杂度 http://t.csdnimg.cn/sxEGF 2 速通数据结构与算法第二站 顺序表 http://t.csdnimg.cn/WVyDb 3 速通数据结构与算法第三站 单链表 http://t.csdnimg.cn/cDpcC 4 速通…

长期提供APX515/B原装二手APX525/B音频分析仪

Audio Precision APx515 是一款针对生产测试而优化的高性能音频分析仪。它因其速度、性能、自动化和易用性而成为一流的仪器。它具有卓越的性能&#xff0c;具有 –106 dB 的典型 THDN、1M 点 FFT 和 192k 数字 I/O&#xff0c;以及所有 APx 系列音频分析仪的一键式自动化和易用…

Flask-1

文章目录 Flask准备创建flask项目flask加载项目配置的二种方式 路由的基本定义接收任意路由参数接收限定类型参数自定义路由参数转换器 终端运行Flask项目http的请求与响应flask的生命周期请求获取请求中各项数据获取请求URL参数获取请求体获取请求头相关信息 响应响应html文本…

通信工程学习:什么是LAN局域网、MAN城域网、WAN广域网

LAN局域网、MAN城域网、WAN广域网 LAN&#xff08;Local Area Network&#xff0c;局域网&#xff09;、MAN&#xff08;Metropolitan Area Network&#xff0c;城域网&#xff09;和WAN&#xff08;Wide Area Network&#xff0c;广域网&#xff09;是计算机网络中根据覆盖范围…

Hive数仓操作(五)

一、Hive 信息查看 Hive的元数据管理&#xff1a; Hive 将表的元数据&#xff08;如表名、列名、类型等&#xff09;存储在关系型数据库中&#xff0c;通常是 MySQL。元数据的主要表包括&#xff1a; TBLS&#xff1a;存储表的信息&#xff08;表名、类型、ID 等&#xff09;。…

VMware NSX Advanced Load Balancer (NSX ALB) 22.1.7 发布下载,新增功能概览

VMware NSX Advanced Load Balancer (NSX ALB) 22.1.7 - 多云负载均衡平台 应用交付&#xff1a;多云负载均衡、Web 应用防火墙和容器 Ingress 服务 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-nsx-alb-22/&#xff0c;查看最新版。原创作品&#xff0c;转载请…

一、Spring Boot集成Spring Security之自动装配

Spring Boot集成Spring Security之自动装配介绍 一、实现功能及软件版本说明二、创建Spring Boot项目三、查看自动装配配置类四、自动装配配置类之SecurityAutoConfiguration1、SecurityAutoConfiguration部分源码2、主要作用3、SpringBootWebSecurityConfiguration3.1、Spring…

D - Hidden Weights

题目链接: D - Hidden Weights (atcoder.jp) 题目描述: 数据范围限制: 样例: 输入: 3 3 1 2 2 3 2 3 1 3 -1 输出: 3 5 2 样例图&#xff1a; 思路&#xff1a; 第一次想的是从没有入节点的点去出发&#xff0c;然后去依次去更新&#xff0c;但是发现这个是错误的。 用dfs…

GPG error golang 1.19

1. 问题描述及原因分析 在飞腾2000的服务器&#xff0c;OS为Kylin Linux Advanced Server release V10环境下&#xff0c;docker版本为18.09.0&#xff08;docker-engine-18.09.0-101.ky10.aarch64&#xff09;&#xff0c;基于容器镜像golang:1.19编译新的容器镜像&#xff0…

图解C#高级教程(二):事件

在现实生活当中&#xff0c;有一些事情发生时&#xff0c;会连带另一些事情的发生。例如&#xff0c;当某国的总统发生换届时&#xff0c;不同党派会表现出不同的行为。两者构成了“因果”关系&#xff0c;因为发生了A&#xff0c;所以发生了B。在编程语言当中&#xff0c;具有…

Motion open Heart 详细动画化开放式心脏解剖

详细和动画的心脏直视解剖。 具有真实的运动和精确的心动周期动画。 包括真实阀门动画序列。 配备高清纹理2048x2048和高清法线贴图,可在教育和游戏方面获得更好、更真实的效果。为(VR)虚拟现实场景和增强现实(AR)做好准备。 下载:​​Unity资源商店链接资源下载链接 …

高职院校“ICT工程师”人才培养方案——以华为认证高级网络工程师HCIP为例

一、引言 在电子信息领域&#xff0c;新技术、新理念和新思路的迅猛发展正推动着信息和网络技术成为各行业产业链的关键部分。信息技术与网络技术的深度融合催生了多样化的应用技术。ICT行业正逐渐渗透到生活的每一个角落&#xff0c;引领着新一轮信息通信产业的发展浪潮。 为…

在LabVIEW中如何读取EXCEL

在LabVIEW中读取Excel文件通常使用“报告生成工具包”&#xff08;Report Generation Toolkit&#xff09;。以下是详细步骤&#xff1a; ​ 安装工具包&#xff1a;确保已安装“报告生成工具包”。这通常随LabVIEW一起提供&#xff0c;但需要单独安装。 创建VI&#xff1a; 打…

一文详解:跨国医疗机构安全合规文件流转的跨境传输解决办法

跨国医疗机构是指那些能够在不同国家之间提供医疗服务的机构&#xff0c;它们通常具有国际化的医疗网络、专业的医疗团队和先进的医疗设备。这些机构不仅能够帮助患者获取国外优质的医疗资源&#xff0c;还能提供包括医疗咨询、治疗安排、病历翻译、签证办理、海外陪同等在内的…

中国联通(海外)数据中心资源:从基础设施运维服务到IDC机房增值服务

在全球化日益加深的今天&#xff0c;企业海外拓展已成为其发展战略的重要一环。然而&#xff0c;面对复杂多变的国际环境和严格的业务要求&#xff0c;如何确保海外业务的高效运行与数据安全&#xff0c;成为了企业亟需解决的关键问题。中国联通国际有限公司凭借其丰富的全球资…

实验5 预备实验1-交换机端口的基本配置

交换机端口的基本配置 &#xff08;本预备实验的重点是四种操作模式的切换&#xff09; 一、实验目的 1、练习cisco 交换机端口的基本配置 二、实验内容和结果 1、新建交换机 2、点击交换机图标&#xff0c;进入CLI窗口&#xff0c;可以看到交换机加电后会进行加电自检&…

[uni-app]小兔鲜-04推荐+分类+详情

热门推荐 新建热门推荐组件, 动态设置组件的标题 <template><!-- 推荐专区 --><view class"panel hot"><view class"item" v-for"item in list" :key"item.id">... ...<navigator hover-class"none&…

在 C++ std::set 中如何利用不同类型的值进行搜索?

在 C 集合中如何利用不同类型的值进行搜索 一、背景二、初衷三、is_transparent四、总结 一、背景 C14 引入了一项引人注目的功能&#xff0c;为关联容器弥补了某些案例中长久以来的不足之处&#xff1a;即允许使用在语义上被视为键&#xff0c;但在技术上并非真正键的值对关联…

VS code Jupyter notebook 导入文件目录问题

VS code Jupyter notebook 导入文件目录问题 引言正文引言 这几天被 VS code 中 Jupyter Notebook 中的文件导入折磨的死去活来。这里特来说明一下放置于不同文件夹下的模块该如何被导入。 正文 首先,我们需要按下 Ctrl + , 键打开设置,然后搜索 notebook file root。在如…

window java17改成java 8

window上装了两个版本的Java&#xff0c;目前全局生效的是Java17&#xff0c;想切换成java8的全局。但是在修改环境变量的Path之后&#xff0c;java -version 还是java 17 但是自己的JAVA_HOME 和Path 都没配错啊… 怕是%JAVA_HOME%\bin\ 有问题&#xff0c;我还特意重写了bin…