JavaEE——简单介绍Thread类以及线程的基本操作
文章目录
- 一、Thread 类中的常见构造方法
- 二、Thread 的一些常见属性
- 三、线程的启动——start()
- isAlive() 方法的解释
- 四、线程中断
- 五、线程等待-join()了解
- 六、简单解释线程休眠
一、Thread 类中的常见构造方法
我们已知,Thread 类是Java中多线程中的一个关键类,因此我们需要知道其较为常用的构造方法,如下图:
Thread t1 = new Thread(); //创建一个线程对象
Thread t2 = new Thread(Runnable()); //实现Runnable接口中的方法
Thread t3 = new Thread(String name); //创建线程对象并且命名
Thread t4 = new Thread(Runnable(),String name); //使用Runnable 接口实现线程对象并且重命名
简单实现最后一种形式的代码:
public class ThreadDemo {public static void main(String[] args) {Thread t = new Thread(new Runnable(){public void run(){while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello");}}},"myThread");t.start();}
}
运行程序,打卡我们的 jconsole 找到我们的 ThreadDemo 线程,连接后就会找到我们自己命名的线程,如下图:
二、Thread 的一些常见属性
- ID 是线程的唯一标识,每一个线程都有对应的id
- 名称 是指在构造方法中自己起的名称,调试时使用
- 状态 状态标识线程当前所处的一种情况
- 优先级 可以用该方法来获取设置优先级,优先级较高的理论上更容易被调度(其实用处不大)
- 是否后台线程 对于后台线程,JVM 会在一个进程的所有非后台线程结束后,才会结束运行。
前台线程:会阻止进程的结束,前台线程的工作未完成,进程就不会结束。
后台线程:不会阻止进程的结束,后台线程如果未完成,而前台线程完成,进程依然可以照常结束。 - 是否存活:简单理解,就是指“run”方法是否结束。
代码解释后台线程
public static void main(String[] args) {Thread t = new Thread(()->{while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello");}});//将线程设定为后台线程t.setDaemon(true);t.start();System.out.println("main");//判断 t 线程是否为后台线程System.out.println("t线程是否为后台线程:"+t.isDaemon());}
三、线程的启动——start()
到目前为止,我们已知可以通过重写 run 方法来创建一个线程对象,但是,线程对象的创建并不意味着线程就可以开始运行。
因此,我通过下面的一个图示来给大家详细解释其中原因:
isAlive() 方法的解释
通过上面的解释我们不难理解,线程的存在与否和线程的开始与否有着密切的关系。
因此,我们可以大致进行设想会出现下面的情况:
- 在 start() 方法前,线程不存在显示 false
- 在线程运行中,线程正在进行显示 true
- 在线程任务结束后显示 false
有了以上的设想,我们就可以通过编写相应的代码进行验证:
public static void main(String[] args) {Thread t = new Thread(()->{try {//设置线程等待,延长线程时间Thread.sleep(100);System.out.println("hello Thread!");} catch (InterruptedException e) {e.printStackTrace();}});//start 方法之前,对线程判断System.out.println(t.isAlive());t.start();//start 后,线程运行中,对线程判断System.out.println(t.isAlive());try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}// 通过等待,线程运行完毕System.out.println(t.isAlive());}
运行截图如下:
这里我实现了设想的三种情况,不难发现符合预期。
总结: 只有调用了 start 方法线程才算正真的从操作系统的底层中被创建出来!
四、线程中断
所谓线程中断,顾名思义,就是让线程在正常运行时因为某些原因需要让其暂停运转,但是,这里的中断,并不是表示让线程立即停止,而只是通知线程,你应该停止了。至于线程是否停止,这取决于代码本身的写法!
- 通过程序员自己设置标志位来终止代码
代码实现:
private static boolean flag = true;public static void main(String[] args) throws InterruptedException {//中断一个线程Thread t = new Thread(() -> {while(flag){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();Thread.sleep(3000);//在主线程里就可以随时通过 flag 变量的取值,来操作 t 线程是否结束flag = false;}
这里的代码就可以解释要让一个线程停止,什么时候停止,全部都是由代码内部来实现的。
注:但是,这种方法存在很大的缺陷,在我们运行代码时就会发现,程序停止时中间会有一个很大的空档期,这就说明自定义变量这种方式反应较慢,尤其是在 sleep 时间较长时,不能做到及时响应。
- 使用 Thread 自带的标志位来终止代码
- 使用 Thread 对象中的 interrupted() 方法来通知线程的结束
代码展示:
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {//1.while中的语句需要注意while(!Thread.currentThread().isInterrupted()){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();Thread.sleep(3000);//2.调用 interrupt 方法告知程序应该结束了t.interrupt();}
解释 while 语句中的代码,如图:
解释 2 处的引用:
即,就是重新设定 Boolean 变量告知线程应该停止。
对于代码整体的运行逻辑进行解释
其实不难发现,这种方法就是将第一种 自定义标志位 的 boolean 操作封装到 Thread 的一个类当中了。
运行结果:
如图所示,我们不难发现,这段代码直接印证了 线程中断,并不是让线程立即停止,而是告诉线程应该停止了 这句话。
到此,我们需要知道 interrupt 会做以下两件事:
- 将线程内 标志位(boolean) 给设置成 true。
- 如果线程正在进行 sleep ,此时就会触发异常,将 sleep 唤醒。
但是,sleep 在唤醒的时候,会将刚才设置的标志位再设定位 false(即,清空标志位)
所以通过以上两点,我们可以更加明确地知道为何在 sleep 报错后,循环仍在继续!
自己设定让线程相应终止请求
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while(!Thread.currentThread().isInterrupted()){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();//要实现线程的及时响应,只需要添加 break 即可//此处可以根据需要添加任意的代码break;}}});t.start();Thread.sleep(3000);t.interrupt();}
五、线程等待-join()了解
在生活中,我们在协同作业的时候常常会遇到等待同伴的情况,线程中也是如此,因此我们也需要一些相应方法来满足需求。
join 的部分相关方法与说明
代码示例:
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{for (int i = 0; i < 3; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// getname()获取自己起的名称System.out.println(Thread.currentThread().getName()+"正在工作");}});Thread t1 = new Thread(t,"李四");Thread t2 = new Thread(t,"张三");t1.start();// 让 t1 先执行,主线程 main 先等待t1.join();System.out.println("李四完成工作,张三开始");t2.start();//让 t2 先执行,主线程 main 先等待t2.join();System.out.println("张三完成任务");}
运行结果
六、简单解释线程休眠
通过前面的许多代码,我相信大家对 sleep() 这个方法的使用并不陌生,下面,我就深入到操作系统内核中来给大家解释一下,线程休眠到底是如何运行做的。
所谓线程休眠,即,就是让此线程不参与调度,不到 CPU 上执行。
相关解释如下图:
需要注意的是,虽然 sleep 方法设定了阻塞时间,但是实际情况要比设定的时间间隔大,因为需要考虑到唤醒后调度的开销,因为对应的线程在唤醒后是无法在第一时间就被调用到 CPU 上执行的!
到此, 文章结束, 如有不足, 欢迎提出. 如有错误, 欢迎指正!
相关文章:

JavaEE——简单介绍Thread类以及线程的基本操作
文章目录一、Thread 类中的常见构造方法二、Thread 的一些常见属性三、线程的启动——start()isAlive() 方法的解释四、线程中断五、线程等待-join()了解六、简单解释线程休眠一、Thread 类中的常见构造方法 我们已知,Thread 类是Java中多线程中的一个关键类&#…...

Java的数据库编程:JDBC
Content 🎉1什么是API 🎉2.什么是JDBC 🎉3.数据库驱动包的安装 🎉4.数据库安装包在idea的使用 🎉5.JDBC的增删改查的简单实现 今天为大家带来JAVA的数据库编程,也就是用Java实现数据库 数据库的最基本的操作就是…...

蓝桥冲刺31天之第六天
今天是摆子的一天,明天我要肝一整天的第四题!!! PS:一个普通的排序罢了 import java.io.*; import java.util.Arrays; import java.util.Scanner;/*** ClassName 考勤刷卡* Description TODO* Author 小怂很怂* Date 2…...
Streamlit 工具记录
Streamlit 是基于 Python 的 Web 应用程序框架,可视化数据,分析结果。 Streamlit 是一个开源库,可在短时间内开发机器学习可视化仪表板。只需几行代码就可以构部署强大的数据应用程序。Streamlit 可将仪表板的开发时间从几天缩短至几小时。 …...

GreenPlum小结
什么是GreenPlum?GreenPlum是业界最快最高性价比的关系型分布式数据库,它在开源的PostgreSQL的基础上采用MPP架构(Massive Parallel Processing,海量并行处理),具有强大的大规模数据分析任务处理能力。GreenPlum作为大数据融合存储…...
C语言中数组和指针
文章目录前言一、指针的概念二、指针的大小三、指针的用法1.指针指向变量2.指针指向数组3.指针指向函数总结前言 本文将给大家带来C语言中非常重要的两个知识点,指针和数组。 一、指针的概念 指针,是C语言中的一个重要概念及其特点,也是掌…...

Leetcode.剑指 Offer II 022 链表中环的入口节点
题目链接 Leetcode.剑指 Offer II 022 链表中环的入口节点 mid 题目描述 给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null。 为了表示给定链表中的环&#…...
4种不同编程语言的打印方式
意义 打印方式是编程中不可或缺的一部分,它可以帮助开发人员有效地调试和测试代码,并提供有用的信息来监视程序的运行状态和性能。 编程语言中的打印方式是指将程序输出到终端或控制台上进行显示。这个功能在编程中非常重要,因为它可以帮助开…...
websocket介绍
我们聊聊轮询技术,什么是轮询?轮询就是在特定的时间间隔,由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。 轮询分为两种: 短轮询:通过不断的向服务端发送数据,客户端发送Request,服务端直接返回Response(不管服务端数据有没有改变)。长轮…...
Educational Codeforces Round 144 (Rated for Div. 2),C,D
C. Maximum Set 思路: 我们求最大数组,显然是L一直乘2,直到再乘2就越过区间位置。我们说过,再乘一个2就不行,那么我们除一个2,换句话说,就是再乘一个4就不行了。发现,我们可能有机会乘一个3&a…...

【redis学习篇】Redis三种持久化方式详解
官方文档 一、Redis持久性 Redis如何将数据写入磁盘 持久性是指将数据写入持久存储,如固态磁盘(SSD)。Redis提供了一系列持久性选项。其中包括: RDB(快照):RDB持久性以指定的时间间隔执行数据…...
垃圾回收中的分代年龄
为什么CMS里的分代年龄是6而不是15 CMS (Concurrent Mark Sweep) 是一种基于分代的垃圾收集器,其中分代年龄指的是一个对象在年轻代中经历了多少次垃圾收集。在 CMS 中,当一个对象的分代年龄达到阈值时,就会被晋升到老年代中。 在 CMS 中&a…...

蓝桥杯-左移右移(2022国赛)
蓝桥杯-左移右移1、问题描述2、解题思路与代码实现2.1 方法一:使用LinkedList双向链表实现(50%)2.2 方法二:使用HashMap左右临界值实现(100%)1、问题描述 小蓝有一个长度为 N 的数组, 初始时从左到右依次是 1,2,3,…N 。 之后小蓝对这个数组进行了 M 次操…...

你还在手撸SQL?ChatGPT笑晕在厕所
文章目录你还在手撸SQL?ChatGPT笑晕在厕所一、背景二、面向Chat编程1. 数据库设计2. 建表语句3. 加中文注释4. 数据模拟5. 查询成绩6. 修改课程任课老师7. 删除课程8. 删除一个有关联数据的课程总结你还在手撸SQL?ChatGPT笑晕在厕所 一、背景 经典3表设…...

【Redis】Redis慢查询
文章目录慢查询记录慢查询两个配置参数修改配置参数慢查询日志慢查询记录 我们都知道像mysql等持久化数据库会有慢查询日志,其实Redis中也有慢查询日志的功能。慢查询就是系统在执行命令的前后计算每条命令的执行时间,如果超过我们预设的时间,…...
【Kubernetes】第二十一篇 - k8s 项目部署流程和操作梳理
一,前言 上一篇,介绍了 k8s 污点和容忍度; 在了解前面 k8s 介绍之后,设计并完成一个前后端项目的部署和持续集成; 本篇,介绍基于 k8s 项目部署流程设计; 二,项目部署流程设计 本…...

推荐系统[九]项目技术细节讲解z2:搜索Query理解[Term Weight、Query 改写、同义词扩写]和语义召回技术
搜索Query理解和语义召回技术 随着用户规模和产品的发展, 搜索面临着越来越大的 query 长尾化挑战,query 理解是提升搜索召回质量的关键。本次将介绍搜索在 query term weighting,同义词扩展,query 改写,以及语义召回等方向上的实践方法和落地情况。 1.面临问题:长尾 qu…...

【项目精选】基于SSH的医院在线挂号系统(视频+论文+源码)
点击下载源码 医院挂号系统主要用于实现医院的挂号,前台基本功能包括:用户注册、用户登录、医院查询、挂号、取消挂号、修改个人信息、退出等。 后台基本功能包括:系统管理员登录、医院管理、科室管理、公告管理、退出系统等。 本系统结构如…...

Pandas库:从入门到应用(一)
一、Pandas简介 pandas是 Python 的核⼼数据分析⽀持库,提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据。pandas是Python进⾏数据分析的必备⾼级⼯具。 pandas的主要数据结构是 **Series(**⼀维数据)与 DataFrame (⼆维数据…...
MySQL中concat()、concat_ws()、group_concat()函数使用
在平时工作中,经常记不清或者记混他们的用法,正好有时间就记录一下~concat()函数语法:concat(str1, str2, int1...)例如执行sql:SELECT CONCAT(id,USERNAME,USER_PHONE) FROM tb_user输出查询结果为: 1test15216756754…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...