java Thread.sleep(0) 有什么用
RocketMQ 中出现 org.apache.rocketmq.store.logfile.DefaultMappedFile#warmMappedFile
作用的交出cpu控制权, 在unix中 使用是时间片算法,而在windows中是抢占式。
在时间片算法中,所有进程使用队列排队。操作系统会按他们的顺序进行分配时间进行执行。该进程在该时间内执行,如果超过时间还没执行完成,将会被剥夺cpu使用权并分配给另外一个进程。如果在该时间内结束或者阻塞。则cpu切换给其他进行。
抢战式就是一个进行得到cpu使用权,除非他主动放弃。不然就会一直霸占这个cpu。 Thead.sleep(0),就是当前线程放弃cpu使用。触发操作系统争夺cpu的争夺。如果更高级别的优先权的进程或者线程要使用,则cpu交给他们使用,没有的话还会返回到当前进程。
而这里因为是for的int ,没有安全点,所以要等到循环结束后才会触发 触发安全点检查 (比如触发GC回收) ,而上面图片中进行让每1000进行触发 安全点检查, 而不是每次都进行。
所以如果for 里面的int循环太多,进行会发生内存溢出的情况,因为没有及时GC。
import java.util.concurrent.atomic.AtomicInteger; public class MainTest { public static AtomicInteger num = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { Runnable runnable = () -> { for (int i = 0; i < 1000000000; i++) { num.getAndAdd(1); } System.out.println(Thread.currentThread().getName() + "执行结束!"); }; Thread t1 = new Thread(runnable); Thread t2 = new Thread(runnable); t1.start(); t2.start(); Thread.sleep(1000); System.out.println("执行结束,num="+num); } }
通过上图的int循环就可以看出来,sleep(1000) 之后,主线程执行结果是等int 循环结束才进行返回 结果的,for循环中没有进行 安全点检查,等结束才进行,也可以for结束了才进行GC 。这都是因为int是可数循环( 后续有介绍) 。
而上图中进行了sleep(0) ,因为吧cpu从当前线程中交出,所以进行了安全点检查,进行GC回收。
通过上图的long循环就可以看出来,sleep(1000) 之后,主线程马上执行结果,而不是等待long循环结束。
下面讲解下 safepoint ,也就是安全点
关于安全点的描述,我们可以看看《深入理解JVM虚拟机(第三版)》的 3.4.2 小节:
可数循环和不可数循环
是HotSpot虚拟机为了避免安全点过多带来过重的负担,对循环还有一项优化措施,认为循环次数较少的话,执行时间应该也不会太长,所以使用int类型或范围更小的数据类型作为索引值的循环默认是不会被放置安全点的。这种循环被称为可数循环(Counted Loop),相对应地,使用long或者范围更大的数据类型作为索引值的循环就被称为不可数循环(Uncounted Loop),将会被放置安全点。
意思就是在可数循环(Counted Loop)的情况下,HotSpot 虚拟机搞了一个优化,就是等循环结束之后,线程才会进入安全点。
反过来说就是:循环如果没有结束,线程不会进入安全点,GC 线程就得等着当前的线程循环结束,进入安全点,才能开始工作。
另外调用native 返回的时候也会触发安全检查,因为native不属于jvm里面。所以从native回来的时候会触发
建议仔细看完“why技术” 写的文章《没有二十年功力,写不出sleep(0)这一行“看似无用”的代码》
https://baijiahao.baidu.com/s?id=1743172147871492575
后面或者又写一篇后续
https://baijiahao.baidu.com/s?id=1743896903429140755&wfr=spider&for=pc
链接跳转不过去的话,在某度搜索关键词:site:baidu.com 没有二十年功力,写不出sleep(0)这一行“看似无用”的代码
java 反编译 工具:HSDIS、JITWatch
引用:
面试官:Thread.sleep(0) 有什么用
没有二十年功力,写不出sleep(0)这一行
JVM系列之:再谈java中的safepoint