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

多线程(三):线程等待获取线程引用线程休眠线程状态

目录

1、等待一个线程:join

1.1 join()

1.2 join(long millis)——"超时时间"

 1.3 join(long millis,int nanos)

2、获取当前线程的引用:currentThread

3、休眠当前进程:sleep

3.1 实际休眠时间

3.2 sleep的特殊写法——sleep(0)

4、线程状态

4.1 NEW

4.2 TERMINATED

 4.3 RUNNABLE

4.4 TIMED_WAITING 

4.5 WAITING


1、等待一个线程:join

1.1 join()

在并发中,我们通常用这样一个需求,一个线程执行完后,另一个线程才能终止,也就是需要控制两个线程结束的先后顺序。

我们可以通过上篇博客所提到的sleep来设置线程的休眠时间,从而控制线程的结束的先后顺序,但是这样的做法是不科学的。比如,我们需要在t线程结束后,让main线程紧跟着结束,此时sleep就显得不靠谱了~~

我们就可以通过:

  • 在main线程中调用t.join()方法,来让main线程等待 t 线程结束后,main再结束。
  • 当代码执行到t.join时,main线程就会发生"阻塞等待",等待t线程结束后,join再继续执行。

join方法也会抛出InterruptedException异常。 

注意:在哪个线程中调用join,就是哪个线程在"阻塞等待"。

1.2 join(long millis)——"超时时间"

其实上文的join是不科学的"等待",其实就是不见不散的“死等”,要是另t线程一直没有结束,main线程就会一直等待下去。

join还提供了另外一个版本,带参数的join(long millis),带有“超时时间”的等待,“超时时间”即最大的等待时间,当等待的时间超过设定的“超时时间”后,main就不会继续等待下去了,继续执行join下面的代码。

例如:在main线程中调用t.join(3000):

  • 当main等待的时间超过3秒后,t线程还没有结束,main就不会继续等待,继续行join下面的代码。
  • 当main等待的时间还没有超过3秒时,即在3秒之内t已经执行完了(t提前结束),此时main也不会再等待了,也会继续行join下面的代码。

带有超时时间的等待,才是更科学的等待(当电脑或者手机程序卡死的时候,就会弹出等待时间的窗口)。尤其是在和网络通信相关的领域都是需要设置"超时时间"。

public class Demo10 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {Thread.currentThread();for(int i = 0; i < 3000; i++) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println("t 线程终止");});t.start();// main 等待 t//t.join();//main 最多等待 t 3秒//t.join(3000);t.join(3000,500);System.out.println("main 终止");}
}

 1.3 join(long millis,int nanos)

join(long millis,int nanos),nanos即纳秒,即"超时时间"精确到纳秒级别,是更为精确的等待。对于我们开发来说,几乎不会使用。

1s = 1000ms(毫秒),1ms = 1000us(微秒),1us = 1000ns(纳秒)

在计算机中,很难做到ns级别的精确测量,即使线程的调度也是ms级别的开销。

但是也并非做不到,"实时操作系统"就可以做到更为精确的时间计算,我们平常接触到的Windows、Linux、Mac、Android系统都不是实时操作系统,这类操作系统常用于航天、军事、工业领域。实时操作系统,其实时性非常高,但是也是在削弱很多功能下达到的,俗话说得好,鱼和熊掌不可兼得~~


2、获取当前线程的引用:currentThread

这个方法我们已经很熟悉了,上篇博客已经为大家进行了讲解。

我们只需要记住一点:在哪个线程中调用,获取的就是哪个线程的引用(类似于this)。


3、休眠当前进程:sleep

3.1 实际休眠时间

这个方法我们也是很熟悉的了。

但是要额外注意一点:实际的休眠时间,往往是要大于我们所设置的休眠时间的。

使用sleep方法让线程休眠时,实际是让当前线程让出CPU资源,当休眠时间一到,只能说明当前线程是允许被操作系统调度到CPU上执行了,而并不是说明是立即被执行。

也就是说还会有一些线程被调度的时间的开销,一般是ms级别的开销。

3.2 sleep的特殊写法——sleep(0)

sleep(0)是使用sleep的一种特殊写法。意味着让当前线程立即放弃CPU资源,让给其他线程,再等待操作系统重新调度。

当一个模块CPU占有率比较高,影响到其他模块正常执行时,就可以通过这种方式来缓解资源紧张。


 到目前为止,基于对Thread类的学习,我们已经掌握了:

  • 创建线程
  • 关键属性
  • 终止线程
  • 线程等待
  • 获取线程引用
  • 线程休眠

接下来,我们再谈线程状态~ 


4、线程状态

我们知道 进程 分为以下两种状态:

  • 就绪
  • 阻塞

但是这两种状态都是站在操作系统的视角所定义的,在Java线程中,Java也是对操作系统线程进行了封装,对于线程状态也是重新进行表示。

  • NEW: 安排了工作, 还未开始行动
  • TERMINATED: 工作完成了
  • RUNNABLE: 可工作的。又可以分成正在工作中和即将开始工作
  • TIMED_WAITING: 这几个都表示排队等着其他事情
  • WAITING: 这几个都表示排队等着其他事情
  • BLOCKED: 这几个都表示排队等着其他事情

4.1 NEW

NEW状态是指:仅仅new好了Thread对象,但是还没有创建线程(还没有start)。

public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("hello t");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});// NEW 状态System.out.println(t.getState());}

4.2 TERMINATED

TERMINATED状态是指:线程已经结束,但是Thread对象依旧存活。即:线程执行完毕。

public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {System.out.println("hello t");});t.start();Thread.sleep(1000);// 此时 t 线程已结束// TERMINATEDSystem.out.println(t.getState());}

 4.3 RUNNABLE

 RUNNABLE状态其实就是就绪状态,分为以下两种:

  1. 线程正在CPU上执行
  2. 线程随时可以去CPU上执行

RUNNABLE是处于NEW和TERMINATED之间的状态。 

public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {}});t.start();// t 线程正在执行// RUNNABLESystem.out.println(t.getState());}

4.4 TIMED_WAITING 

TIMED_WAITING状态是一种阻塞状态(不参与CPU调度,不继续执行了),但是是有指定时间的阻塞,阻塞的时间有上限。

当线程处于以下状态时就为TIMED_WAITING状态。

  1. sleep指定时间内休眠时
  2. 处于使用带"超时时间"的阻塞等待时

线程sleep前为RUNNABLE状态,sleep时为TERMINATED状态,sleep后又回到RUNNABLE状态。

public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (true) {try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();// TIMED_WAITINGThread.sleep(1000);System.out.println(t.getState());}

4.5 WAITING

WAITING也是一种阻塞状态,只不过是死等,即没有"超时时间"的阻塞等待。

public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (true){}});t.start();// 没有超时时间的阻塞等待t.join();// 此时main线程就处于 WAITING状态}

END

相关文章:

多线程(三):线程等待获取线程引用线程休眠线程状态

目录 1、等待一个线程&#xff1a;join 1.1 join() 1.2 join(long millis)——"超时时间" 1.3 join(long millis&#xff0c;int nanos) 2、获取当前线程的引用&#xff1a;currentThread 3、休眠当前进程&#xff1a;sleep 3.1 实际休眠时间 3.2 sleep的特殊…...

Hi3244 应用指导

Hi3244 是一款DIP8封装高性能、多模式工作的原边控制功率开关。Hi3244内高精度的恒流、恒压控制机制结合完备的保护功能&#xff0c;使其适用于小功率离线式电源应用中。在恒压输出模式中&#xff0c;Hi3244 采用多模式工作方式&#xff0c;即调幅控制&#xff08;AM&#xff0…...

【LeetCode热题100】哈希

1.两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素。 你可以按任意顺序返回答…...

Java的四种循环语句

背景&#xff1a; Java 中主要有四种循环语句&#xff1a;for 循环、while 循环、do-while 循环 和 foreach 循环&#xff08;也称为增强型 for 循环&#xff09;。下面我将分别介绍这四种循环语句&#xff0c;并给出相应的实例。 for循环&#xff1a; 1. for 循环for 循环是…...

Qt杂记目录

Qt 杂记目录 QMenu 1.menu转string Qt 窗口阴影边框...

项目开发--基于docker实现模型容器化服务

背景 1、docker-compose build 和 docker-compose up -d分别是什么作用&#xff1f; 2、如何进入新构建的容器当中 3、模型保存的方法区别 4、如何让docker容器启动的时候能使用cuda进行模型推理加速 5、如何实现容器的迭代 解决方案 问题1 docker-compose build 和 docker…...

C语言 | Leetcode C语言题解之第477题汉明距离总和

题目&#xff1a; 题解&#xff1a; int totalHammingDistance(int* nums, int numsSize) {int ans 0;for (int i 0; i < 30; i) {int c 0;for (int j 0; j < numsSize; j) {c (nums[j] >> i) & 1;}ans c * (numsSize - c);}return ans; }...

Bug剖析

Bug剖析 • 所有的Bug报告有以下的基本要求&#xff1a; • 标题。要简略。 • 指派。谁来处理这个问题。 • 重现步骤。问题再次出现的相关步骤。 • 优先级别。问题的紧迫性与重要性。 • 严重程度。问题所产生的后果。 • 解决方案。怎么解决问题。 其他很多方面对修复问题…...

HI3516DV500 相机部分架构初探

Hi3516DV500 是一颗面向视觉行业推出的高清智能 Soc。该芯片最高支持 2 路 sensor 输入&#xff0c;支持最高 5M30fps 的 ISP 图像处理能力&#xff0c;支持 2F WDR、多级降噪、六轴防 抖、多光谱融合等多种传统图像增强和处理算法&#xff0c;支持通过 AI 算法对输入图像进行实…...

训练yolo系列出现问题mAP, R, P等为零

1. 问题 40系列显卡训练yolo系列出现问题&#xff0c;loss正常&#xff0c;但mAP&#xff0c;R&#xff0c;P等为零。 环境&#xff1a;ultralytics版本为8.3.9&#xff0c;cuda11.8&#xff0c; torch2.4。 40系列显卡网上说可以使用cuda低于11.7的&#xff0c;自己测试了下…...

数字媒体技术基础:色度子采样(4:4:4、4:2:2 、4:2:0)

在数字视频处理中&#xff0c;色度子采样 Chroma Subsampling可以用于压缩视频文件的大小&#xff0c;同时在大多数情况下保持较高的视觉质量&#xff0c;它的原理基于人类视觉系统对亮度 Luminance比对色度 Chrominance更加敏感这一特点。 一、 采样格式的表示方法 色度子采样…...

tkinter库的应用小示例:文本编辑器

tkinter库的应用小示例&#xff1a;文本编辑器 要 求&#xff1a; 创建一个文本编辑器&#xff0c;功能包括&#xff0c;创建、打开、编辑、保存文件。一个Button小组件&#xff0c;命名为btn_open,用于打开要编辑的文件&#xff0c;一个Button小组件&#xff0c;命名为btn_s…...

信息抽取数据集处理——RAMS

引言 RAMS数据集&#xff08;RAMS&#xff1a;Richly Annotated Multilingual Schema-guided Event Structure&#xff09;由约翰斯霍普金斯大学于2020年发布&#xff0c;是一个以新闻为基础的事件抽取数据集。它标注了9,124个事件&#xff0c;涵盖了139种不同的事件类型和65种…...

SpringBoot+XXL-JOB:高效定时任务管理

前言 在现代应用程序中&#xff0c;定时任务是不可或缺的一部分。Spring Boot 和 XXL-Job 为你提供了一个强大的工具组合&#xff0c;以简化任务调度和管理。 本文将带领你探索如何将这两者集成在一起&#xff0c;实现高效的定时任务管理。无论你是初学者还是有经验的开发者&…...

openpyxl -- 简介

文章目录 介绍核心类 介绍 开源的python读写Excel的工具库&#xff0c;由志愿者在业余时间维护&#xff1b;安装&#xff0c;pip install openpyxl;官方文档地址源码地址issues列表默认openpyxl不能保证抵御大量的xml攻击&#xff0c;为抵御这些攻击需安装defusedxml&#xff…...

滚雪球学MySQL[8.3讲]:数据库中的JSON与全文检索详解:从数据存储到全文索引的高效使用

全文目录&#xff1a; 前言8.3 JSON与全文检索1. JSON数据类型的使用1.1 JSON 数据类型概述1.2 JSON 数据的插入与查询1.3 JSON 常用函数与操作1.4 JSON使用的优缺点与性能考虑 2. 全文索引与全文检索2.1 全文索引概述2.2 全文检索的使用2.3 全文检索模式2.4 全文索引优化与性能…...

position定位静态定位/绝对定位/相对定位

1.静态定位static&#xff1a;按照标准流进行布局 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>D…...

2024年09月CCF-GESP编程能力等级认证C++编程三级真题解析

本文收录于专栏《C++等级认证CCF-GESP真题解析》,专栏总目录:点这里。订阅后可阅读专栏内所有文章。 一、单选题(每题 2 分,共 30 分) 第 1 题 下列代码中,输出结果是( ) #include<iostream> using namespace std; i...

Web自动化Demo-PHP+Selenium

1.新建工程 打开PhpStorm新建工程如下&#xff1a; 打开终端输入如下命令安装selenium&#xff1a; composer require php-webdriver/webdriver 2.编写代码 <?php require vendor/autoload.php;use Facebook\WebDriver\Remote\RemoteWebDriver; use Facebook\WebDriver…...

Python速成笔记——知识(GUI自动化处理屏幕和按键输出)

处理屏幕 获取屏幕快照 函数:pyautogui.screenshot(); 【注】该函数返回包含一个屏幕快照的Image对象; 分析屏幕快照 函数:pyautogui.pixel(); 【注】 传递一个坐标的元组,函数返回坐标对应像素点的RGB值(RGB元组) 函数:pyautogui.pixelMatchesColor() 【注】 函数第一…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...