Thread.sleep(0)的实际运用

无意间在某公众号中发现了关于RocketMq源码的的一张图片,看到Thread.sleep(0)可以prevent gc 感到十分震惊,想探究其中的奥秘,于是阅读了相关文章之后似乎有了一点感觉,遂记录下来,顺便希望通过这篇文章能够让我延续记录的习惯。

在了解这行代码之前,首先需要大概了解java gc的stw(stop the world)以及safepoint两个知识点。大概就是如果当前程序进入safepoint后会检测stw标志位,如果stw为true则需要进行一次gc后再继续程序。

counted loop 可数循环

counted loop(可数循环)中,jvm是不会进入safepoint的。简单来说 如果你的当前循环是counted loop,那么jvm会在所有循环结束之后在进入safepoint完成gc,此时循环产生的垃圾数量可能会让此次gc时间更长,从而导致性能下降。

那什么是counted loop

-------《深入理解JVM虚拟机(第三版)》:
在这里插入图片描述
从中可以看到,如果使用int或更小范围类型作为索引值的话是不会放置安全点的,这种循环成为counted loop可数循环,那我们很容易就知道不可数循环是通过使用long及long以上的类型作为索引值的循环。
所以由此我们可以知道,在源码中如果不手动进入safepoint 那么只有在整个循环完毕才会进入safepoint检查stw标志位,那么此时经过循环之后需要gc的垃圾可能会很多,可能会导致gc时间过长而影响性能。

那么 为什么 Thread.sleep(0)可以阻止这种情况?

在这里插入图片描述
本图摘选自知乎 https://www.zhihu.com/question/29268019/answer/43762165,作者:RednaxelaFX
可以看到在调用jni(java native interface) 的时候会进入safepoint

为了证实这一观点 我们去看看cpp的源码
https://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/tip/src/share/vm/runtime/safepoint.cpp
在这里插入图片描述
源码确认无疑 那么我们再去看看Thread.sleep()是否是jni就能破案。
打开sleep源码 前面的native给了我们答案。

在这里插入图片描述

至此,这几行代码的作用我们已经十分明了,把循环结束执行的长时gc切割为循环过程中手动进入的小gc,从而减少gc对系统性能的影响。

所以不要再说Thread.sleep(0)没有用了!我对我自己说

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值