• 欢迎访问本站,本站记录博主日常编程遇到的问题,知识,惊奇软件等。如有问题还请留言


    Deprecated: strip_tags(): Passing null to parameter #1 ($string) of type string is deprecated in /www/wwwroot/gschaos.club/wp-content/themes/Git-alpha-6h0SRk/header.php on line 294

java.sleep()

java mysticalycc 5个月前 (03-31) 86次浏览 已收录 0个评论

java的thread.sleep方法是会响应中断的,cpu会使用定时器,定时器到时会触发中断让cpu调度这个线程,但是我不明白java中将线程设置中断,为什么sleep可以响应中断指令,是怎么做到的?

java 的 Thread.sleep() 为什么可以响应 interrupt()

java 中,Thread.sleep() 会放弃 CPU 执行权,并由 硬件定时器 触发中断来唤醒线程。那么,如果另一个线程在 sleep() 期间调用了 interrupt(),为什么 sleep() 能立即响应并抛出 InterruptedException 呢? 这背后的机制涉及 硬件定时器、CPU 调度 和 java 线程的中断管理


1. Thread.sleep() 背后的工作原理

当线程调用 Thread.sleep(millis) 时,jvm 并不会让它在 CPU 上空等,而是依赖 操作系统的定时器 来实现暂停:

  1. jvm 调用操作系统的定时睡眠 API
    • Linux 下:调用 nanosleep()clock_nanosleep()
    • Windows 下:调用 Sleep()
    • 这些系统调用会让线程进入 阻塞(Blocked)或超时等待(Timed Waiting)状态,同时向 硬件定时器 注册一个计时任务。
  2. 硬件定时器(Timer)开始计时
    • CPU 里的定时器(如 APIC、HPET)开始倒计时。
    • CPU 继续执行其他线程,而不会轮询等待。
  3. 定时器超时,触发中断
    • millis 时间到达时,定时器向 CPU 发送中断信号(Timer Interrupt)
    • CPU 停止当前任务,进入 中断处理程序(Interrupt Handler),让操作系统调度 睡眠线程重新进入就绪队列(Ready Queue)
  4. 线程恢复执行
    • 线程从 sleep() 返回,继续执行后续代码。

✅ 关键点:CPU 不会轮询定时器,而是等定时器超时后 触发硬件中断,然后调度被阻塞的线程。


2. Thread.interrupt() 如何影响 Thread.sleep()

如果另一个线程在 sleep() 期间调用了 interrupt(),java 线程是如何立即响应的呢?这涉及 操作系统的睡眠管理 和 jvm 的中断检测

(1)interrupt() 设置中断标志

thread.interrupt() 被调用时:

  • 目标线程的 中断标志位(interrupted flag)被设置为 true
  • 但此时线程 仍然处于阻塞(sleep)状态,它本身不会主动检查中断。

(2)操作系统会提前唤醒 sleep() 线程

  • 在大多数操作系统(如 Linux、Windows)中,调用 interrupt() 会强制唤醒 sleep() 线程!
  • 例如,在 Linux 下:
    • Thread.sleep() 本质上调用 nanosleep()
    • interrupt() 会向 sleep() 线程发送信号(Signal,如 SIGALRM,打断它的 nanosleep(),导致 sleep() 提前返回并抛出 EINTR 错误。

(3)jvm 检测到中断并抛出 InterruptedException

  • Thread.sleep() 在被系统强行唤醒时,会检查线程的中断状态
    • 如果线程的 interrupted 标志位为 truejvm 立刻抛出 InterruptedException,并清除中断标志。
    • 如果没有 interrupt(),线程正常睡眠到超时后才返回

(4)线程可以在 catch 语句中决定如何处理

class SleepInterruptDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("Thread sleeping...");
                Thread.sleep(5000); // 进入 sleep
                System.out.println("Thread woke up normally.");
            } catch (InterruptedException e) {
                System.out.println("Thread was interrupted while sleeping!");
            }
        });

        thread.start();

        try {
            Thread.sleep(2000); // 让主线程先等 2 秒
        } catch (InterruptedException e) {}

        thread.interrupt(); // 2 秒后中断线程
    }
}

可能的输出:

Thread sleeping...
Thread was interrupted while sleeping!

可以看到,线程本来应该睡 5 秒,但 interrupt() 在 2 秒后提前唤醒了它。


3. 总结

机制 Thread.sleep() 的行为
正常情况下 线程调用 sleep(),进入 阻塞状态,等待定时器超时,CPU 运行其他任务。
定时器超时 硬件定时器触发中断,OS 让线程进入 就绪队列,等待 CPU 调度。
调用 interrupt() 操作系统 强制唤醒睡眠线程,jvm 发现线程的 中断标志位,抛出 InterruptedException

java 线程不会主动轮询中断状态,而是依赖 OS 直接唤醒线程。
操作系统的 sleep() API(如 nanosleep())本身就支持被 interrupt() 强制打断。
jvm 发现 interrupt() 后,立即抛出 InterruptedException,使 sleep() 提前返回。


4. 为什么 sleep() 能响应中断?

可以简单理解为:

  1. sleep() 调用的是操作系统的定时器,让线程进入 阻塞状态
  2. 操作系统会在 interrupt() 发生时 强制唤醒 这个线程。
  3. jvm 发现线程被唤醒,同时中断标志为 true,就抛出 InterruptedException

这样,sleep() 就能优雅地响应 interrupt(),让线程有机会决定如何处理中断! 🚀


MysticalYcc , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:java.sleep()
喜欢 (0)
mysticalycc
关于作者:
简短的个人签名

Warning: Attempt to read property "comment_author_email" on null in /www/wwwroot/gschaos.club/wp-content/themes/Git-alpha-6h0SRk/comments.php on line 47
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到