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

news2024/12/28 22:25:29

目录

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 线程已结束
        // TERMINATED
        System.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 线程正在执行
        // RUNNABLE
        System.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_WAITING
        Thread.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

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

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

相关文章

Canvas:AI协作的新维度

在人工智能的浪潮中&#xff0c;OpenAI的最新力作Canvas&#xff0c;不仅是一款新工具&#xff0c;它标志着人工智能协作方式的一次革命性飞跃。Canvas为写作和编程提供了一个全新的交互界面&#xff0c;让用户能够与ChatGPT进行更紧密、更直观的协作。 ​​​​​​​ Canvas的…

LeetCode 面试经典150题 Z字形变换

题目&#xff1a; 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a; P A H N A P L S I I G Y I R 之后&#xff0c;你…

无人机无线电侦测核心技术详解

无人机无线电侦测核心技术主要涉及频谱分析、信号处理、定位技术以及智能化识别等多个方面。以下是对这些核心技术的详细解析&#xff1a; 1. 频谱分析技术 频谱探测技术&#xff1a;通过分析信号在频域上的分布和特性&#xff0c;来识别、测量和定位无线电信号。在无人机侦测…

leetcode 491.非递减子序列

1.题目要求: 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作递增序列的一种特殊情况。 …

Python | Leetcode Python题解之第477题汉明距离总和

题目&#xff1a; 题解&#xff1a; class Solution:def totalHammingDistance(self, nums: List[int]) -> int:n len(nums)ans 0for i in range(30):c sum(((val >> i) & 1) for val in nums)ans c * (n - c)return ans

BUUCTF-Business Planning Group1

下载是一张PNG图片&#xff0c; 使用010editor打开发现尾部有隐藏文件 把这段16进制字符串复制到新文件并改名为1.bpg 使用bpgviewer软件查看 Release Simple BPG Image viewer asimba/pybpgviewer GitHub Notes: large images will be scaled to fit screen areabasic s…

[单master节点k8s部署]40.安装harbor

harbor 是私有镜像仓库&#xff0c;用来存储和分发镜像的 。docker 还有一个官方的镜像仓库 docker hub&#xff0c;免费用户只能简单的使用&#xff0c;创建一个私有镜像仓库&#xff0c;存储镜像&#xff0c;付费用户才可以拥有更多权限&#xff0c;默认 docker pull 拉取镜像…

nginx搭建视频下载站

目录 1.前言与介绍 2.atuoindex模块介绍 3.主要的功能 4.下载站基本要求 5.具体配置 6.做完如上的配置重载服务 7.创建密码文件 8.在windows主机上做域名解析 9.查看统计结果 1.前言与介绍 前面的学习中根据nginx的简单的配置实现了根据 IP 端口 和 域名 实现虚…

MySQL-三范式 视图

文章目录 三范式三范式简介第一范式第二范式第三范式 表设计一对一一对多多对多最终的设计 视图 三范式 三范式简介 所谓三范式, 其实是表设计的三大原则, 目的都是为了节省空间, 但是三范式是必须要遵守的吗? 答案是否定的(但是第一范式必须遵守) 因为有时候严格遵守三范式…

AI开发-三方库-Hugging Face-Tokenizer

1 需求 需求1&#xff1a;from transformers import AutoTokenizer 需求2&#xff1a;from transformers import BertTokenizer 2 接口 关键参数 textpaddingtruncationreturn_tensors 3 示例 BertTokenizer.from_pretrained() PreTrainedTokenizer PreTrainedTokenizerBa…

医疗图像之基于Unet++的息肉分割

第一步&#xff1a;准备数据 息肉分割数据&#xff0c;总共有1000张 第二步&#xff1a;搭建模型 UNet&#xff0c;这是一种旨在克服以上限制的新型通用图像分割体系结构。如下图所示&#xff0c;UNet由不同深度的U-Net组成&#xff0c;其解码器通过重新设计的跳接以相同的分…

CountUp.js 实现数字增长动画 Vue

效果&#xff1a; 官网介绍 1. 安装 npm install --save countup.js2. 基本使用 // template <span ref"number1Ref"></span>// script const number1Ref ref<HTMLElement>() onMounted(() > {new CountUp(number1Ref.value!, 9999999).sta…

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; }

超GPT3.5性能,无限长文本,超强RAG三件套,MiniCPM3-4B模型分享

MiniCPM3-4B是由面壁智能与清华大学自然语言处理实验室合作开发的一款高性能端侧AI模型&#xff0c;它是MiniCPM系列的第三代产品&#xff0c;具有4亿参数量。 MiniCPM3-4B模型在性能上超过了Phi-3.5-mini-Instruct和GPT-3.5-Turbo-0125&#xff0c;并且与多款70亿至90亿参数的…

元组与列表嵌套用法

1.可以对列表中的元素修改&#xff0c;不能对元组中的元素修改&#xff1b;当元组与列表嵌套时遵循上述原则. 下图为元组与列表的嵌套案例&#xff08;学生信息的完善&#xff09;&#xff1a;

QQ快捷键冲突解决方法

注意&#xff1a;快捷键被占用&#xff0c;更改快捷键后使用不了&#xff0c;是因为有其他系统快捷键被占用&#xff0c;多尝试几个就可以了

计算机是如何输入存储输出汉字、图片、音频、视频的

计算机是如何输入存储输出汉字、图片、音频、视频的 为了便于理解&#xff0c;先了解一下计算机的组成。 冯诺依曼计算机的五大组成部分。分别是运算器、控制器、存储器、输入设备和输出设备。参见下图&#xff1a; 一、运算器 运算器又称“算术逻辑单元”&#xff0c;是计算…

Golang | Leetcode Golang题解之第477题汉明距离总和

题目&#xff1a; 题解&#xff1a; func totalHammingDistance(nums []int) (ans int) {n : len(nums)for i : 0; i < 30; i {c : 0for _, val : range nums {c val >> i & 1}ans c * (n - c)}return }

SQLI LABS | SQLI LABS 靶场初识

关注这个靶场的其它相关笔记&#xff1a;SQLI LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;SQLI LABS 靶场简介 SQLi-Labs 靶场是一个专门用于学习和测试 SQL 注入漏洞的开源靶场&#xff0c;该靶场提供了多个具有不同漏洞类型和难度级别的 Web 应用程序的环境。这些应用…

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

题目&#xff1a; 题解&#xff1a; class Solution { public:int totalHammingDistance(vector<int> &nums) {int ans 0, n nums.size();for (int i 0; i < 30; i) {int c 0;for (int val : nums) {c (val >> i) & 1;}ans c * (n - c);}return …