一、Thread.sleep 源码
public static native void sleep(long millis) throws InterruptedException;
sleep方法是本地方法,通过系统调用暂停当前线程,而java语言本身是无法实现的
二、sleep 方法特点一
阻塞调用该方法的线程(运行态变为阻塞态),让出CPU资源,让其他线程竞争CPU资源;sleep时间结束后进入就绪状态,重新竞争CPU资源
- thread0先启动,但是由于thread0调用了sleep方法,让出CPU资源,自己进入阻塞状态
- thread1获得CPU资源,线程由就绪态转运行态,thread1打印结果,在其执行结束后,释放了CPU资源;
- thread0的sleep时间结束后,进入就绪状态,重新竞争CPU资源,获得CPU资源后,由就绪态转到运行态,打印结果
三、sleep 方法特点二
阻塞调用该方法的线程(运行态变为阻塞态),让出CPU资源,但不释放自己占有的锁,让其他线程竞争CPU资源;sleep时间结束后进入就绪状态,重新竞争CPU资源
- 由结果可知,当thread0调用sleep方法后,thread1 虽然获得了cpu资源,但是由于Thread0没有释放锁,所以Thread1无法获得锁,只能由运行态转阻塞态并加入同步队列,同时释放自己占有的CPU资源;
- thread0 的sleep时间结束后,重新获得CPU资源,执行结束并释放锁并通知同步队列;
- thread1 获得锁,打印输出 (在这里我们暂且把synchronized作为一个重量级锁来说明)
四、关于sleep方法深入理解
1、调用Thread.Sleep(1000),在1s后线程会不会被立即唤醒?
Thread.Sleep(1000) 只是通知操作系统,在未来的1s内我不想再参与到CPU竞争。当1s后,此时如果有一个线程正在使用CPU,那么操作系统是不会重新分配CPU的,只能等到当前运行线程挂起或结束;即使1s后恰巧轮到操作系统进行CPU 分配,那么当前线程也不一定能抢到CPU资源。
2、代码中出现Thread.Sleep(0)到底有没有意义?
Thread.Sleep(0) 就是通知操作系统在0毫秒内,当前线程不参与cpu分配,操作系统收到指令后立即重新计算所有线程的优先级,重新发起CPU资源分配,也许是当前线程获得CPU资源,也许是其他线程。
在执行时间较长的逻辑里或者执行时间较长的循环中,可以使用Thread.Sleep(0)该方法,发起CPU资源重新分配;
注意:操作系统会监控CPU占用情况,如果发现某个线程长时间霸占CPU,会强制使这个线程挂起,因此在实际上不会出现“一个线程一直占用 CPU 不放”的情况。