当前位置: 首页 > news >正文

多线程Thread常用方法和状态

Thread类 及常见方法

1、常见构造方法

方法说明
Thread()创建线程对象
Thread(Runnable target)使用 Runnable 对象创建线程对象
Thread(String name)创建线程对象,并命名
Thread(Runnable target, String name)使用 Runnable 对象创建线程对象,并命名
Thread(ThreadGroup group,线程可以被用来分组管理,分好的组即为线程组(了解即可,不详细讲)

上篇文章基本上都讲解过了,我们这里只讲解两个Thread(String name)以及Thread(Runnable target, String name) 来讲解

这两个方法都可以在创建线程的时候,给线程起给名字(这个名字运行重复),目的就是为了方便程序员调试。一旦出问题,就更方便找到对应的代码。

如果不自定义名字,JVM 就会按照thread-0 ,thread-1…来命名

1.1Thread(Runnable target, String name)

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

通过jconsole来查看验证:

image-20230221223255358

2、Thread 的几个常见属性

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

ID:

Java中给Thread对象安排的身份标识;和操作系统内核中的PCB的pid以及和操作系统提供的线程线程API中的线程id都不是一回事。

名称:

就是前面构造方法中我们自己自定义的名称

状态:

下面单独讲。

优先级:

获取线程的优先级

后台线程:

默认创建的是前台线程,后台线程指的是当所有(main线程)前台线程执行完毕以后,不管后台线程有没有执行完,直接退出进程。前台进程就不会。

是否存活:

判定内核的线程在不在!

Thread对象虽然和内核中的线程是一一对应的,但是生命周期并非完全相同。

Thread t = new Thread();这样虽然Thread对象出来了,内核里的线程还不一定有;

调用start方法,内核线程才会有,当内核里的线程执行完了(run方法运行完了),内核的线程就销毁了,但是Thread对象还在。

[经典的面试题]

调用 start 才会真正创建线程!! 不调用 start 没创建线程 (在内核里创建 PCB)
注意理解, start 和 run 的区别!! **
直接调用 run 并没有创建线程,只是在原来的线程中运行的代码
调用 start,则是
创建了线程**,在新线程中执行代码(和原来的线程是并发的)

线程的中断:

run方法执行完了,线程就结束了.有没有办法,让线程,提前一点结束呢??

通过线程中断的方式来进行;

本质:让run方法尽快结束,而不是run执行一半强制结束。

目前常见的有以下两种方式:

  1. 通过共享的标记来进行沟通

  2. 调用 interrupt() 方法来通知

1、通过共享的标记来进行沟通:

image-20230222004144060

2、使用标准库里面自带的一个标志位

使用 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替自定义标志位

方法说明
public static boolean interrupted()判断当前线程的中断标志位是否设置,调用后清除标志位
public boolean isInterrupted()判断对象关联的线程的标志位是否设置,调用后不清除标志位

使用 thread 对象的 interrupt() 方法通知线程结束.

在主线程,通过thread.interrupt()设置标志位为true!

2.1使用Thread.currentThread().isInterrupted()判断当前线程的中断标志被设置

image-20230222012016003

启动时我们发现:

image-20230222012055034

报错了,并且线程也没有中断,为什么?

2.1.1、interrupt方法的行为,有两种情况:

1、t线程在运行状态:

调用t.interrupt()会设置标志位为true。结果**!**后正常中断。

image-20230222012331417

2、线程在阻塞状态( wait/join/sleep 等方法而阻塞挂起)

不会设置标志位,而是触发一个InterruptedException 异常的形式通

知,清除中断标志,并且提前将阻塞状态唤醒!

前面有讲到线程中断的本质是:本质:让run方法尽快结束,而不是run执行一半强制结束。

下面就可以体现出来,当遇到InterruptedException 异常的形式通知时候。会触发这个异常:

image-20230222012644466

具体的如何处理,就在于补抓到异常以后用户的代码是如何写

①立即结束进程:

image-20230222012818394

②不理会:

QQ录屏20230222013027 00_00_00-00_00_30

③稍后处理:

image-20230222013253379

2.2使用Thread.interrupted() 判断当前线程的中断标志被设置

image-20230222013842513

当这个使用这个作为标志位时候调用thread.interrupt()时候问题同上;

他们两个方法的不同之处就在于:

image-20230222014008962

什么叫做清楚标志位,什么叫做不清除?

清除标志位:

public class ThreadDemo {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()-> {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().interrupted());}});thread.start();thread.interrupt();}
}

打印结果:

true // 只有一开始是 true,后边都是 false,因为标志位被清

false

false

false

false

false

false

false

false

false

不清除标志位:

public class ThreadDemo {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()-> {for (int i = 0; i < 10; i++) {System.out.println(Thread.interrupted());}});thread.start();thread.interrupt();}
}

true // 全部是 true,因为标志位没有被清

true

true

true

true

true

true

true

true

true

3、等待一个线程-join()

join()可以控制线程之间的结束顺序

线程之间的调度顺序,是不确定的!!可以通过一些特殊操作,来对线程的执行顺序,做出干预其中 join 就是一个办法,控制线程之间的结束顺序!!

Tips:Java 中的多线程方法,只要是这个方法会阻塞,都可能会抛出InterrupttedException 异常!!

效果:在main中调用t.join效果就是让main线程阻塞等待,等到t执行完了,main才继续执行!!

public class ThreadDemo {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()-> {for(int i = 0; i < 10; i++) {}});t.start();t.join();}
}

当调用t.join()时候,main线程进入阻塞,不参与CPU的调度。

方法说明
public void join()等待线程结束
public void join(long millis)等待线程结束,最多等 millis 毫秒
public void join(long millis, int nanos)等待线程结束,最多等 millis 毫秒,但可以更高精度

实际应用:

服务器开发经常要处理客户端的请求,根据请求计算生成响应 就需要用到“等待时间”称为“超时时间“客户端发了请求过来,等待响应,这个等待就不能无限的等 可以根据需要,约定 1000ms 500ms如果时间之内响应没有回来,客户端直接提示“等待超时

4、获取当前线程引用

public static Thread currentThread() :返回当前线程对象的引用

5、休眠当前线程

注意:由于线程的调度是不可控制的,所以,这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间的

方法说明
public static void sleep(long millis) throws InterruptedException休眠当前线程 millis毫秒
public static void sleep(long millis, int nanos) throws可以更高精度的休眠

sleep:指定休眠的之间(阻塞一会会)

如何更加好的理解sleep?

操作系统管理这么多个PCB的时候是有多个链表的,调用了sleep,则当前调用sleep的PCB就会被移动到另外的“阻塞队列”中。如图:

image-20230222084250484

image-20230222084341685

通过上诉案例我们也能够清楚的认识到,使用sleep(1000)的话,实际阻塞时间是大于等于1s的,这完全取决于调度了。

状态-Thread常见属性

这里特指Java中的对Thread的状态规则

NEW:Thread对象创建出来了,但是内核的PCB还没创建。

TERMINATED:内核的PCB销毁了,但是Thread对象还在。

RUNNABLE:就绪状态(正在CPU上运行 + 在就绪队列中排队)

TIMED_WAITING:按照一定的时间,进行阻塞。

WAITING:特殊的阻塞状态(调用wait)

BLOCKED:等待锁的时候竟然的阻塞状态

一个线程状态之间的变化如下图:

image-20230222184010978

相关文章:

多线程Thread常用方法和状态

Thread类 及常见方法 1、常见构造方法 方法说明Thread()创建线程对象Thread(Runnable target)使用 Runnable 对象创建线程对象Thread(String name)创建线程对象&#xff0c;并命名Thread(Runnable target, String name)使用 Runnable 对象创建线程对象&#xff0c;并命名Thre…...

Codeforces Round #836 (Div. 2)

A SSeeeeiinngg DDoouubbllee 题意&#xff1a;告诉你一个字符串。若该串上每一位上的字母都可以出现两次&#xff0c;求回文串 思路&#xff1a;正向再反向输出s即可 #include <bits/stdc.h> #define lowbit(x) x&(-x) #define ios cin.sync_with_stdio(false)…...

Python学习之项目实践: 写一个MP3播放器

下面呢&#xff0c;是一个 Python MP3 播放器&#xff0c;它使用 pygame 模块来实现音乐播放功能&#xff1a; import pygame class MP3Player: """ MP3 播放器类 """ def __init__(self): pygame.mixer.init() def play(self, file_path): &quo…...

RocketMQTemplate 实现消息发送

代码托管于gitee&#xff1a;easy-rocketmq 文章目录一、前置工作二、消费者三、生产者1. 普通消息2. 过滤消息3. 同步消息4. 延时消息5. 批量消息6. 异步消息7. 单向消息8. 顺序消息9. 事务消息概要Demo源码解读一、前置工作 1、导入依赖 <dependency><groupId>…...

教师干货丨这5款微课必备提效神器,我要告诉全世界!

微课是一种短小精悍的视频教学形式&#xff0c;其设计和演示因特别简洁明了而被定义为“小而美”。由于只在几分钟时间内向学生传授所需知识&#xff0c;微课为学习者提供更多的选择机会和时间节约的便利&#xff0c;而这种趋势已经逐渐在新的社交媒体环境中显现出来。在制作微…...

timm使用swin-transformer

1.安装 pip install timm2.timm中有多少个预训练模型 #timm中有多少个预训练模型 model_pretrain_list timm.list_models(pretrainedTrue) print(len(model_pretrain_list), model_pretrain_list[:3])3加载swin模型一般准会出错 model_ft timm.create_model(swin_base_pat…...

【java基础】java八大基本数据类型和运算符

文章目录说明八大基本数据类型整型浮点型字符型布尔类型类型转换java运算符基础运算符二元运算符自增自减运算符关系和boolean运算符三元运算符位运算符运算符优先级说明 这里介绍java的八大基本数据类型和运算符 八大基本数据类型 java中有八大数据类型&#xff0c;4个整型…...

Mybatis源码学习笔记(四)之Mybatis执行增删改查方法的流程解析

1 Mybatis流程解析概述 Mybatis框架在执行增伤改的流程基本相同&#xff0c; 很简单&#xff0c;这个大家只要自己写个测试demo跟一下源码,基本就能明白是怎么回事&#xff0c;查询操作略有不同&#xff0c; 这里主要通过查询操作来解析一下整个框架的流程设计实现。 2 Mybat…...

浅谈测试用例设计

前言 最近干的最多的事情就是设计测试用例、评审测试用例了&#xff0c;于是我不禁又想到了一个经典的问题&#xff1a;如何设计出优秀的测试用例&#xff1f; 可能有些童鞋看到这个问题会有些不以为然&#xff0c;这有什么好想的&#xff1f;干个测试谁还不会设计测试用例&a…...

python 利用装饰器实现类似于flask路由

例子1&#xff1a; def f1():print(1111)def f2():print(2222)if __name__ __main__:print(33)打印结果&#xff1a; 33 在例子1中&#xff0c;f1() 与f2() 都没有被调用&#xff0c;只执行了print(33) f1与f2&#xff0c;是没有被调用的&#xff0c;但是如果f1 和 f2 上面…...

git 拉取远程分支到本地

目录&#xff1a;***&#xff01;本小作者&#xff0c;是将终端和Git的可视化插件结合使用&#xff0c;刚接触的可以自习看一下&#xff0c;内容简单&#xff0c;避免弯路&#xff01;***一&#xff0c;简单了解远程分支1&#xff0c;连接远程&#xff1a;2&#xff0c;提交&am…...

Answering Multi-Dimensional Range Queries under Local Differential Privacy

文章目录AbstractIntroduction2 PRELIMINARIES2.12.2 Categorical Frequency Oracles4 GRID APPROACHES4.1概述Abstract 在本文中&#xff0c;我们解决了在局部差异隐私下回答多维范围查询的问题。有三个关键的技术挑战&#xff1a;捕捉属性之间的相关性&#xff0c;避免维度的…...

手把手搭建springboot项目05-springboot整合Redis及其业务场景

目录前言一、食用步骤1.1 安装步骤1.1.1 客户端安装1.2 添加依赖1.3 修改配置1.4 项目使用1.5 序列化二、应用场景2.1 缓存2.2.分布式锁2.2.1 redis实现2.2.2 使用Redisson 作为分布式锁2.3 全局ID、计数器、限流2.4 购物车2.5 消息队列 (List)2.6 点赞、签到、打卡 (Set)2.7 筛…...

Flutter基础语法(六)var、final、const、late

Flutter基础 第六章 Flutter关键字var、final、const、late的区别与使用 文章目录Flutter基础前言一、var1.var是什么?2.var如何使用3.var自动推断类型4.var可以再次赋值5.var指定类型二、final1.final是什么?2.final声明但不赋值3.final赋值多次4.final正常使用三、const1.…...

Linux之安装node

Linux之安装node步骤如下 1.去网站下载node 下载地址&#xff1a; https://npm.taobao.org/mirrors/ 2.上传到指定目录下 3.解压 tar -zxvf node-v17.3.0-linux-x644.配置node环境变量 //执行以下命令 vim /etc/profile //在path中加入以下内容 /usr/local/node-v15.14.0/b…...

二叉树、二叉搜索树、二叉树的最近祖先、二叉树的层序遍历【零神基础精讲】

来源0x3f&#xff1a;https://space.bilibili.com/206214 文章目录二叉树[104. 二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)[111. 二叉树的最小深度](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)[129. 求根节点到叶节点…...

【算法】【数组与矩阵模块】求最长可整合子数组和子数组的长度

目录前言问题介绍解决方案代码编写java语言版本c语言版本c语言版本思考感悟写在最后前言 当前所有算法都使用测试用例运行过&#xff0c;但是不保证100%的测试用例&#xff0c;如果存在问题务必联系批评指正~ 在此感谢左大神让我对算法有了新的感悟认识&#xff01; 问题介绍 …...

数据结构:循环队列的实现(leetcode622.设计循环队列)

目录 一.循环队列简单介绍 二.用静态数组实现循环队列 1.数组循环队列结构设计 2.数组循环队列的堆区内存申请接口 3.数据出队和入队的接口实现 4.其他操作接口 5.数组循环队列的实现代码总览 三.静态单向循环链表实现循环队列 1.链表循环队列的结构设计 2.创建静…...

[qiankun]实战问题汇总

[qiankun]实战问题汇总ERROR SyntaxError: Cannot use import statement outside a module问题分析解决方案子应用命名问题问题分析解决方案jsonpFunction详细错误信息问题分析解决方案微应用的注册问题Uncaught Error: application cli5-beta6-test-name died in status LOADI…...

Kafka(6):服务端常用参数配置

参数配置&#xff1a;config/server.properties # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership.…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...