Java中线程的常用方法(并发编程基础)

Java中线程的常用方法

sleep

  1. 调用sleep会让当前线程从Running进入TIMED WAITING状态
  2. 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时sleep方法会抛出InterruptedException
  3. 睡眠结束后的线程未必会立刻得到执行
  4. 建议用TimeUnitsleep代替Threadsleep来获得更好的可读性

实例代码

public class SleepMethodDemo {public static void main(String[] args) {Logger log = Logger.getLogger("SleepMethodDemo");Thread t1 = new Thread(() -> {try {//                Thread.sleep(1000);//建议使用log.info("Thread t1 sleep 1000ms");TimeUnit.MICROSECONDS.sleep(1000);} catch (InterruptedException e) {log.info("Thread t1 interrupted");e.printStackTrace();}}, "t1");t1.start();log.log(Level.INFO, "main thread end");t1.interrupt();}}

控制台输出
在这里插入图片描述

这里的TimeUtit本质上还是去调用了Thread.sleep(),只是可读性增强,我们可以查看一下源码

在这里插入图片描述

yield

  1. 调用yield会让当前线程从Running进入Runnable就绪状态,然后调度执行其它线程
  2. 具体的实现依赖于操作系统的任务调度器(当cpu很空闲时,也就是没有太多资源抢占到cpu,哪怕执行此方法,操作系统也会将时间片给当前线程)

sleep 和 yield的区别

  1. sleep会有一段真正的等待时间,而yield基本上是马上执行
  2. sleep是将线程变为TIMED_WAITING状态,此时是不会被操作系统调度的,而yield是将线程变为就绪状态,是可以继续被系统调度的,也就是还是能够抢占cpu.

线程优先级

  • 线程优先级会提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它
  • 如果cpu比较忙,那么优先级高的线程会获得更多的时间片,但cpu闲时,优先级几乎没作用.
    public class YieldAndPriority {public static void main(String[] args) {Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {int i = 0;while (true) {System.out.println(Thread.currentThread().getName() + " " + i++);}}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {int i = 0;while (true) {Thread.yield();//让出cpuSystem.out.println("       "+Thread.currentThread().getName() + " " + i++);}}});//设置优先级,优先级范围为1-10t1.setPriority(Thread.MAX_PRIORITY);t2.setPriority(Thread.MIN_PRIORITY);t1.start();t2.start();}}

sleep的应用

在没有利用cpu来计算时,不要让while(true)空转浪费cpu,这时可以使用yield或sleep来让出cpu的使用权给其他程序

    while(true){try{Thread.sleep(50);}catch(InterruptedException e){e.printStackTrace();}}
  • 可以用wait或条件变量达到类似的效果
  • 不同的是,后两种都需要加锁,并且需要相应的唤醒操作,一般适用于要进行同步的场景
  • sleep适用于无需锁同步的场景.

join

join方法实际上就是在一个线程当中等待另一个线程结束以后才开始执行自己的代码

该方法有两种,一种带参一种无参.

  • join() 等待线程运行结束
  • join() 等待线程运行结束,最多等待n毫秒

若线程执行完毕小于设定的最多等待时间,不会继续等待,以两者比较的最小值为准.

interrupt

打断 sleep,wait,join 的线程,会清空打断状态,打断过后,打断状态设为false.正常线程打断设置为true(但正常线程打断并不会立即停止运行,只是注上一个打断标记)

  • 示例: 打断sleep,wait,join线程.
    public class InterruptMethodDemo {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {System.out.println("t1 is interrupted");e.printStackTrace();}}, "t1");System.out.println("start t1");t1.start();t1.interrupt();TimeUnit.MICROSECONDS.sleep(50);System.out.println("t1.isInterrupted() = " + t1.isInterrupted());}}

结果展示
在这里插入图片描述

  • 示例:打断正常的线程
    public class InterruptNormalDemo {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {while (true) {}}, "t1");System.out.println("t1.start");t1.start();t1.interrupt();System.out.println("t1.interrupt()");TimeUnit.SECONDS.sleep(1);System.out.println("t1.isInterrupted() = " + t1.isInterrupted());}}

此时,线程t1并没有结束,而是继续在运行.

在这里插入图片描述

我们将代码改写,手动控制线程的执行与停止

    public class InterruptNormalDemo {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {while (true) {System.out.println("while t1.isInterrupted() = " + Thread.currentThread().isInterrupted());if(Thread.currentThread().isInterrupted()){break;}}}, "t1");System.out.println("t1.start");t1.start();Thread.sleep(1);t1.interrupt();System.out.println("t1.interrupt()");TimeUnit.SECONDS.sleep(1);System.out.println("t1.isInterrupted() = " + t1.isInterrupted());}}

结果为
在这里插入图片描述

实践运用interrupt(两阶段终止)

场景分析: 当前有一个业务,用来日志监控,每隔两秒进行监控,中途若被打断,停止监控.

我们可以运用两阶段终止的设计模式来进行.哪么是哪两个阶段呢

  • 第一个阶段,正常打断,也就是我们没有在线程睡眠时打断,此时打断标记为true
  • 第二个阶段,睡眠打断,也就是我们在线程睡眠时打断,此时打断标记为false

为了完成此业务,我们应该在睡眠打断后抛出异常的过程中,再次重置打断标记,也就是置为false,这样我们就能正确停止.

代码如下

    @Slf4j(topic = "c.DoubleInterruptDemo")public class DoubleInterruptDemo {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {while (true){Thread currentThread = Thread.currentThread();// 判断是否中断if(currentThread.isInterrupted()){log.info("处理后事");break;}try {TimeUnit.SECONDS.sleep(1);log.info("日志监控");} catch (InterruptedException e) {e.printStackTrace();// 重新设置中断状态log.debug("重新设置中断状态");currentThread.interrupt();}}});t1.start();TimeUnit.SECONDS.sleep(4);t1.interrupt();}}

结果如下
在这里插入图片描述

注意一下,介绍一下Thread.interrupted(),这个方法会返回当前线程的打断标记,若为true,将值返回后会自动重新刷新为false.

两阶段终止很好的替代了stop()方法.

过时方法

  • stop(): 停止进程运行,相当于直接杀死进程,这样容易造成死锁,因为可能这个线程拿到了锁的资源,直接杀死导致锁资源没有被释放,别的线程获取不到锁,造成死锁.

  • suspend(): 挂起(暂停)线程运行

  • resume(): 恢复线程运行

    后面两个方法被设计用来暂停和恢复线程的执行,但由于它们的使用不当可能导致线程永远挂起

    假设有两个线程 A 和 B,线程 A 在执行过程中调用了线程 B 的 suspend() 方法来暂停线程 B,然后线程 A 需要在某个条件满足时恢复线程 B,于是调用了线程 B 的 resume() 方法。如果线程 A 在调用 resume() 方法之前被阻塞或结束了,那么线程 B 将永远被挂起,导致死锁

具体原因

  1. 死锁风险:如上例所示,使用 suspend() 和 resume() 容易导致线程之间的死锁,特别是在多线程环境下,线程间的执行顺序难以预测和控制。
  2. 不一致的状态:在线程被 suspend() 暂停时,它可能持有一些重要的资源锁。如果此时其他线程试图访问这些资源,它们将被阻塞,从而导致系统性能下降或死锁。
  3. 难以调试:使用 suspend() 和 resume() 可能导致线程的行为变得难以预测和调试,特别是在复杂的系统中。

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

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

相关文章

昇思25天学习打卡营第08天 | 模型训练

昇思25天学习打卡营第08天 | 模型训练 文章目录 昇思25天学习打卡营第08天 | 模型训练超参数损失函数优化器优化过程 训练与评估总结打卡 模型训练一般遵循四个步骤: 构建数据集定义神经网络模型定义超参数、损失函数和优化器输入数据集进行训练和评估 构建数据集和…

【致知功夫 各随分限】成长需要时间,助人须考虑对方的承受程度

帮助他人需考虑各人的分限所能及的,初学圣学需时间沉淀,存养心性 任何人都应该受到教育,不应受到贫富、贵贱的差异而排除在教育之外,对于不同材质的学生,需要因材施教; 每天都有新的认知,大我…

基于工业互联网的智慧矿山解决方案PPT(38页)

文章摘要 工业互联网与智慧矿山 基于工业互联网的新一代智慧矿山解决方案,将互联网和新一代IT技术与工业系统深度融合,形成关键的产业和应用生态,推动工业智能化发展。该方案以“四级、三层、两网、一平台”为总体框架,强调应用目…

[Vite]Vite插件生命周期了解

[Vite]Vite插件生命周期了解 Chunk和Bundle的概念 Chunk: 在 Vite 中,chunk 通常指的是应用程序中的一个代码片段,它是通过 Rollup 或其他打包工具在构建过程中生成的。每个 chunk 通常包含应用程序的一部分逻辑,可能是一个路由视…

2024菜鸟春招笔试

第一题 解题思路: 签到题,把帖子按好评度降序排列,再将人按升序排列。 第二题 解题思路 从左到右遍历,如果当前元素没有错排,将其与后一个交换,这样两个元素一定都错排。 第三题 、 解题思路 这题当时暴力…

智能运维场景探索 | 运营分析

【本场景来源于 擎创科技《一体化数智运维AIOps解决方案》白皮书,经过重新编写】 该场景主要围绕生产运行、运营决策两个维度进行展开,通过对配置、性能、业务等运行数据的加工计算,形成可量化运营效果、可衡量发展方向的运营数据。整体以低…

陈志泊主编《数据库原理及应用教程第4版微课版》的实验题目参考答案实验2

实验目的 1.掌握在SQL Server中使用对象资源管理器和SQL命令创建数据库与修改数据库的方法。 2.掌握在SQL Server中使用对象资源管理器或者SQL命令创建数据表和修改数据表的方 法(以SQL命令为重点)。 实验设备 操作系统:Win11…

CV03_mAP计算以及COCO评价标准

COCO数据集回顾:CV02_超强数据集:MSCOCO数据集的简单介绍-CSDN博客 1.1 简介 在目标检测领域中,mAP(mean Average Precision,平均精度均值)是一个广泛使用的性能评估指标,用于衡量目标检测模型…

MongoDB集群搭建-最简单

目录 前言 一、分片概念 二、搭建集群的步骤 总结 前言 MongoDB分片(Sharding)是一种水平扩展数据库的方法,它允许将数据分散存储在多个服务器上,从而提高数据库的存储容量和处理能力。分片是MongoDB为了应对大数据量和高吞吐量需…

创新引领未来,智慧水利在路上:数字孪生技术为水库管理开辟新机遇,带来新挑战,引领水利行业迈向智能化新纪元

目录 前言 一、数字孪生技术概述 二、新机遇:数字孪生技术如何重塑水库管理 1、精准预测,科学调度 2、智能监测,及时预警 3、优化资源配置,提升管理效率 4、促进公众参与,增强透明度 三、新挑战:数字…

Fill - UVA 10603

网址如下&#xff1a; Fill - UVA 10603 - Virtual Judge (vjudge.net) 感觉有点浮躁&#xff0c;没法完全将思绪投入题的思考中 脑袋糊糊的 一道bfs题 代码如下&#xff1a; #include<queue> #include<cstdio> #include<cstring> #include<vector&g…

奇迹MU 骷髅战士在哪

BOSS分布图介绍 我为大家带来各地区怪物分布图。在游戏前期&#xff0c;很多玩家可能会不知道该去哪里寻找怪物&#xff0c;也不知道哪些怪物值得打。如果选择了太强的怪物&#xff0c;弱小的玩家可能会无法抵御攻击。如果选择了低等级的boss&#xff0c;收益可能并不理想。所…

吴恩达机器学习 第三课 week3 强化学习(月球着陆器自动着陆)

目录 01 学习目标 02 概念 2.1 强化学习 2.2 深度Q学习&#xff08;Deep Q-Learning &#xff09; 03 问题描述 04 算法中的概念及原理 05 月球着陆器自动着陆的算法实现 06 拓展&#xff1a;基于pytorch实现月球着陆器着陆 07 总结 写在最前&#xff1a;关于强化学习…

【MindSpore学习打卡】应用实践-自然语言处理-基于RNN的情感分类:使用MindSpore实现IMDB影评分类

情感分类是自然语言处理&#xff08;NLP&#xff09;中的一个经典任务&#xff0c;广泛应用于社交媒体分析、市场调研和客户反馈等领域。本篇博客将带领大家使用MindSpore框架&#xff0c;基于RNN&#xff08;循环神经网络&#xff09;实现一个情感分类模型。我们将详细介绍数据…

UE5 07-给物体添加一个拖尾粒子

添加一个(旧版粒子系统)cascade粒子系统组件 ,在模板中选择一个开发学习初始包里的粒子

智慧文旅(景区)解决方案PPT(42页)

智慧文旅解决方案摘要 行业分析中国旅游业正经历消费大众化、需求品质化、发展全域化和产业现代化的发展趋势。《“十三五”旅游业发展规划》的发布&#xff0c;以及文化和旅游部的设立&#xff0c;标志着旅游业的信息化和智能化建设成为国家战略。2018年推出的旅游行业安全防范…

cs224n作业4

NMT结构图&#xff1a;&#xff08;具体结构图&#xff09; LSTM基础知识 nmt_model.py&#xff1a; 参考文章&#xff1a;LSTM输出结构描述 #!/usr/bin/env python3 # -*- coding: utf-8 -*-""" CS224N 2020-21: Homework 4 nmt_model.py: NMT Model Penchen…

2024年导游资格证题库备考题库,高效备考!

1.台湾著名的太鲁阁公园的特色是&#xff08;&#xff09;。 A.丘陵和溶洞 B.森林和瀑布 C.峡谷和断崖 D.彩林和彩池 答案&#xff1a;C 解析&#xff1a;台湾著名的太鲁阁公园的特色是峡谷和断崖。 2.下列位于台湾的景区中&#xff0c;素有"神秘的森林王国"之…

51单片机STC89C52RC——15.1 AD/DA(模数数模)

目的/效果 1 LCD1602 显示 可调电阻、光敏电阻、热敏电阻值&#xff08;AD&#xff09; 2 模拟信号控制LED明暗&#xff08;DA&#xff09; 一&#xff0c;STC单片机模块 二&#xff0c;AD/DA 2.1 AD/DA 介绍 AD&#xff08;Analog to Digital&#xff09;&#xff1a;模拟…

金丝键合强度测试仪试验条件要求:键合拉脱/引线拉力/剪切力等

金丝键合强度测试仪是测量引线键合强度&#xff0c;评估键合强度分布或测定键合强度是否符合有关的订购文件的要求。键合强度试验机可应用于采用低温焊、热压焊、超声焊或有关技术键合的、具有内引线的器件封装内部的引线-芯片键合、引线-基板键合或内引线一封装引线键合&#…