我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Thread.sleep(0)的写法原理深入解析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Thread.sleep(0)的写法原理深入解析

前言

最近在网上看到了一段代码,让我感到很迷茫。他在代码中使用了 Thread.sleep(0),让线程休眠时间为0秒,具体代码如下。

int i = 0;
while (i<10000000) {
    // business logic
    //prevent long time gc
    if (i % 3000 == 0) {
        try {
            Thread.sleep(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

sleep了0秒,不就是不睡觉吗?我的第一反应是这段代码没什么用,但是看到他的注释又引起了我的兴趣。经过一番研究,看似无用的一段代码,其实大有文章。

探索分析

为了找到原因,首先去看下sleep方法的javadoc,如下:

Causes the currently executing thread to sleep (temporarily ceaseexecution) for the specified number of milliseconds, subject tothe precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.

显然没有得到正确的答案,最后在询问作者说是使用Thread.sleep(0)可以暂时释放CPU时间线。

时间片循环调度算法

在操作系统中,CPU有很多竞争策略。Unix系统采用时间片循环调度算法。在该算法中,所有进程都被分组到一个队列中。操作系统按顺序为每个进程分配一定的时间,即允许进程运行的时间。如果在时间片结束时进程仍在运行,则CPU将被剥夺并分配给另一个进程,如果进程在时间片内阻塞或结束,则CPU立即切换。调度程序所要做的就是维护一个就绪进程表。当进程用完时间片时,它将被移到队列的末尾。

上面的代码中存在死循环。作者希望一直用一个线程来处理业务逻辑。如果Thread.sleep(0)不使用主动放弃CPU时间片,线程资源会一直被占用。众所周知,GC 线程具有低优先级,因此Thread.sleep(0)用于帮助 GC 线程尝试竞争 CPU 时间片。但是为什么作者说可以防止long time GC呢?这就讲到JVM的垃圾回收原理了。

GC的安全点

HotSpot虚拟机为例,JVM并不会在代码指令流的任何位置暂停以启动垃圾回收,而是强制执行必须到达安全点才暂停。换句话说,在到达安全点之前,JVM 不会为 GC STOP THE WORLD

JVM 会在一些循环跳转和方法调用上设置安全点。不过,为了避免安全点过多带来的沉重负担,HotSpot虚拟机还有一个针对循环的优化措施。如果循环次数少,执行时间不宜过长。因此,默认情况下不会将使用 int 或更小数据类型作为索引值的循环放置在安全点中。这种循环称为可数循环。相应地,使用long或更大范围的数据类型作为索引值的循环称为未计数循环,将被放置在安全点。

但是,我们这里正好有一个可数循环,所以我们的代码不会放在安全点。因此,GC线程必须等到线程执行完毕,才能执行到最近的安全点。但如果使用Thread.sleep(0),则可以在代码中放置一个安全点。我们可以看下HotSpotsafepoint.cpp源码中的注释,做除了说明。

// Begin the process of bringing the system to a safepoint.
// Java threads can be in several different states and are
// stopped by different mechanisms:
//
//  1. Running interpreted
//     The interpeter dispatch table is changed to force it to
//     check for a safepoint condition between bytecodes.
//  2. Running in native code
//     When returning from the native code, a Java thread must check
//     the safepoint _state to see if we must block.  If the
//     VM thread sees a Java thread in native, it does
//     not wait for this thread to block.  The order of the memory
//     writes and reads of both the safepoint state and the Java
//     threads state is critical.  In order to guarantee that the
//     memory writes are serialized with respect to each other,
//     the VM thread issues a memory barrier instruction
//     (on MP systems).  In order to avoid the overhead of issuing
//     a memory barrier for each Java thread making native calls, each Java
//     thread performs a write to a single memory page after changing
//     the thread state.  The VM thread performs a sequence of
//     mprotect OS calls which forces all previous writes from all
//     Java threads to be serialized.  This is done in the
//     os::serialize_thread_states() call.  This has proven to be
//     much more efficient than executing a membar instruction
//     on every call to native code.
//  3. Running compiled Code
//     Compiled code reads a global (Safepoint Polling) page that
//     is set to fault if we are trying to get to a safepoint.
//  4. Blocked
//     A thread which is blocked will not be allowed to return from the
//     block condition until the safepoint operation is complete.
//  5. In VM or Transitioning between states
//     If a Java thread is currently running in the VM or transitioning
//     between states, the safepointing code will wait for the thread to
//     block itself when it attempts transitions to a new state.

可以看上面的第2点 Running in native code,而Thread.sleep(long millis)是一种native方法。

总结

Thread.sleep(0)不是什么无用的代码。sleep 方法可用于在 java 代码中放置一个安全点。可以提前在长循环中触发GC,避免GC线程长时间等待,从而避免达到拉长GC时间的目的。

以上就是Thread.sleep(0)的写法原理深入解析的详细内容,更多关于Thread.sleep(0)写法原理的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Thread.sleep(0)的写法原理深入解析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Thread.sleep(0)的写法原理深入解析

这篇文章主要为大家介绍了Thread.sleep(0)的写法原理深入解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-27

GoComparableType原理深入解析

这篇文章主要为大家介绍了GoComparableType原理深入解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-06

Flutter渲染原理深入解析

众所周知 Flutter是由Google推出的开源的高性能跨平台框架,一个2D渲染引擎。在Flutter中,Widget是Flutter用户界面的基本构成单元,可以说一切皆Widget。下面来看下Flutter框架的整体结构组成
2023-05-15

SpringBoot启动原理深入解析

我们开发任何一个SpringBoot项目都会用到启动类,下面这篇文章主要给大家介绍了关于SpringBoot启动原理解析的相关资料,文中通过图文以及实例代码介绍的非常详细,需要的朋友可以参考下
2023-05-14

gosync.Map基本原理深入解析

这篇文章主要为大家介绍了gosync.Map基本原理深入解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-28

Golangsync.Map原理深入分析讲解

go中map数据结构不是线程安全的,即多个goroutine同时操作一个map,则会报错,因此go1.9之后诞生了sync.Map,sync.Map思路来自java的ConcurrentHashMap
2022-12-17

Android10 Binder原理概述深入解析

这篇文章主要为大家介绍了Android10 Binder原理概述深入解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

深入解析Golang中锁的工作原理

Golang中锁的工作原理深度剖析引言:在并发编程中,避免竞态条件(race condition)是至关重要的。为了实现线程安全,Golang提供了丰富的锁机制。本文将深入剖析Golang中锁的工作原理,并提供具体的代码示例。一、互斥锁(M
深入解析Golang中锁的工作原理
2023-12-28

深入解析Go语言的并发原理

哈喽!今天心血来潮给大家带来了《深入解析Go语言的并发原理》,想必大家应该对Golang都不陌生吧,那么阅读本文就都不会很困难,以下内容主要涉及到,若是你正在学习Golang,千万别错过这篇文章~希望能帮助到你!Go语言中并发的本质解读Go
深入解析Go语言的并发原理
2024-04-04

深入学习Android ANR 的原理分析及解决办法

目录一、ANR说明和原因1.1 简介1.2 原因1.3 避免二、ANR分析办法2.1 ANR重现2.2 ANR分析办法一:Log2.3 ANR分析办法二:traces.txt2.4 ANR分析办法三:Java线程调用分析2.5 ANR分析办
2022-06-07

flutter布局约束原理深入解析

这篇文章主要为大家介绍了flutter布局约束原理深入解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-13

深入解析MySQL MVCC 原理与实现

深入解析MySQL MVCC 原理与实现MySQL是目前最流行的关系型数据库管理系统之一,它提供了多版本并发控制(Multiversion Concurrency Control,MVCC)机制来支持高效并发处理。MVCC是一种在数据库中处
2023-10-22

ReactHooks核心原理深入分析讲解

这篇文章主要介绍了reacthooks实现原理,文中给大家介绍了useStatedispatch函数如何与其使用的FunctionComponent进行绑定,节后实例代码给大家介绍的非常详细,需要的朋友可以参考下
2022-12-17

React Streaming SSR原理示例深入解析

这篇文章主要为大家介绍了React Streaming SSR原理示例深入解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-20

深入理解Oracle锁表原因分析

深入理解Oracle锁表原因分析,需要具体代码示例随着企业数据库规模的不断增长和复杂性的加深,数据库锁表问题逐渐成为数据库管理员以及开发人员需要面对和解决的重要挑战之一。在Oracle数据库中,锁表是指当一个会话获取了对某个表或者行的锁之
深入理解Oracle锁表原因分析
2024-03-10

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录