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

Java 为什么不推荐在 while 循环中使用 sleep() 我悟了

文章目录

  • 前言
  • 原因是否正确
  • 方案是否合理
    • 定时轮询场景
    • 事件机制
    • 等待和唤醒
  • 个人简介

前言

  • 最近逛 CSDN 看到一篇文章,文章大意是说为什么在循环中不推荐使用 sleep 操作,原因在于线程挂起和唤醒会有很大的性能消耗,并推荐使用 Timer 及 ScheduledExecutorService 方案进行优化,下面我简单复现一下具体代码,大家思考一下,原文的原因以及解决方案是否合理:
public class Demo {private static final boolean FLAG = true;public static void main(String[] args) {while (FLAG) {try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}}// do something}
}
  • 上面的代码你可能会得到下面的警告:
Call toThread.sleep()’ in a loop, probably busy-waiting
// 循环中调用 sleep 可能会导致忙等待 
// 如 FLAG 变量状态未改变 那么线程可能一直循环,并不断进行线程挂起和唤醒

1698754459535.png

原因是否正确

  • 主要原因和原文博主所说有很大的关系但不完全正确:
  • 我们都知道 Java 线程实际对应着操作系统中的一个线程,对线程的挂起和唤醒是一个很耗性能的操作,因此我们需要避免对线程进行挂起和唤醒;
  • 但还一个重要的原因是忙等待,如上文所示 FLAG 变量的状态可能永远不会被改变,那么线程将会不断进行挂起和唤醒,进入忙等待状态,造成资源的浪费。

方案是否合理

  • 记住一点,讨论方案永远不能脱离场景,没有一种方案可以适应所有的场景,我们永远只是在探讨适合当前场景的方案。因此,原文博主只是提供了一些场景下的方案,下面我们结合一些具体的场景来探讨一些可行的方案:

定时轮询场景

  • 定时轮询的场景我们可以采用博主提供的思路,比如 Timer 及 ScheduledExecutorService 或者其它一些定时机制方案。
比如微服务体系中,客户端上报实例状态,或者服务端检测客户端状态都会使用定时轮询的机制。

事件机制

  • 上文的场景,我更推荐事件机制进行解耦,当变量被改变时,发送变量修改事件进行处理,如常见的 Spring Event 或者其它事件推送框架。
比如一些用户登录场景,当用户登录状态改变时,发送登录事件进行后续处理,比如登录通知等等

等待和唤醒

  • 等待和唤醒机制一般适用于等待时间较长的场景,因为等待和唤醒是一个性能消耗比较大的操作;在等待时间不是很长的场景可以使用轮询机制,避免线程频繁的挂起和唤醒。
在 Java AQS 等待获取锁和线程池任务为空等待新任务时,会使用等待和唤醒操作
轮询机制 和 等待和唤醒 一般会结合使用,避免线程频繁的挂起和唤醒。

个人简介

👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.

🚀 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。

🧠 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。

💡 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。

🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

📖 保持关注我的博客,让我们共同追求技术卓越。

http://www.lryc.cn/news/217286.html

相关文章:

  • 编程新手的犯错之路
  • 高级 Python:函数
  • 【学习笔记】[PA2019] Osady i warownie 2
  • Flask——接口路由技术
  • Dubbo篇---第一篇
  • powermock-成员变量赋值
  • Axios请求成功和失败时分别执行哪个函数?
  • 【Linux】进程概念III --fork函数解析
  • 关闭 Android SplashScreen(闪屏)
  • react_16
  • 前端性能分析工具
  • 根据Aurora发送时序,造Aurora 数据包,从而进行AXIS接口数据位宽转换仿真
  • java后端响应结果Result
  • react_11
  • AI:52-基于深度学习的垃圾分类
  • [shell,hive] 在shell脚本中将hiveSQL分离出去
  • 求两个(法)向量之间的rpy夹角
  • [100天算法】-每个元音包含偶数次的最长子字符串(day 53)
  • 从科幻走向现实,LLM Agent 做到哪一步了?
  • [笔记] 数据类型
  • QT学习之QT概述
  • 编写shell脚本,利用mysqldump实现MySQL数据库分库分表备份
  • 本地部署Jellyfin影音服务器并实现远程访问影音库
  • 【数据结构】希尔排序
  • 使用VBA打印PDF文件
  • 分布式ID系统设计(2)
  • http和https的区别,以及https涉及到的加密过程
  • 使用php打印时间精确到毫秒及毫秒转成11位时间戳
  • uni-app离线打包在android studio创建的.jks证书,签名文件获取MD5问题
  • 333333333333