You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

中断阻塞/睡眠线程的行为及程序运行异常疑惑

Java线程中断问题深度解析

一、待解答问题

1. 基础问题

中断处于阻塞或睡眠状态的线程会发生什么?

2. 选择题

当对因调用join、sleep或wait方法而阻塞的线程调用interrupt方法后,会发生以下哪种情况?
选项:

  • 线程进入非可运行状态
  • 线程退出非可运行状态
  • 线程进入运行状态时抛出InterruptedException
  • 抛出InterruptedException后调用Thread.interrupted()会返回true
  • 以上都不是

二、测试程序与输出

Program 1

public class JavaApplication1 { 
    public static void main(String[] args) { 
        try { 
            Thread.sleep(2000); 
            boolean interrupted = Thread.interrupted(); 
            System.out.println(interrupted); 
            Thread currentThread = Thread.currentThread(); 
            System.out.println("Current Thread ID : " + currentThread.getId()); 
            System.out.println("State : " + currentThread.getState()); 
            
            Thread t = new Thread(() -> System.out.println("runnable target")); 
            System.out.println("Thread t not started yet : " + t.getState()); 
            System.out.println("Thread t not started yet : " + t.isAlive()); 
            System.out.println("T id : " + t.getId()); 
            
            Thread t2 = new Thread(() -> { 
                for (int i = 0; i < 10; i++) { 
                    try { 
                        System.out.println("runnable target"); 
                        if (i == 5) { 
                            Thread.sleep(2000); 
                        } 
                    } catch (InterruptedException ex) { 
                        Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex); 
                    } 
                } 
            }); 
            t2.start(); 
            
            System.out.println("T id : " + t2.getId()); 
            System.out.println("default priority : " + t2.getPriority()); 
            
            System.out.println("interrupting the main thread---"); 
            currentThread.interrupt(); 
            System.out.println("Current Thread ID : " + currentThread.getId()); 
            System.out.println("State : " + currentThread.getState()); 
            System.out.println("State : " + currentThread.isInterrupted()); 
            
            System.out.println("interrupting the t2 thread---"); 
            t2.interrupt(); 
            System.out.println("Current Thread ID : " + t2.getId()); 
            System.out.println("State : " + t2.getState()); 
            System.out.println("State : " + t2.isInterrupted()); 
            
        } catch (InterruptedException ex) { 
            System.out.println("Interrupted Exception :" + ex); 
        } 
    } 
}

Program 1 输出

false
Current Thread ID : 1
State : RUNNABLE
Thread t not started yet : NEW
Thread t not started yet : false
T id : 10
T id : 11
default priority : 5
interrupting the main thread---
Current Thread ID : 1
State : RUNNABLE
State : true
interrupting the t2 thread---
Current Thread ID : 11
State : RUNNABLE
State : true
runnable target
runnable target
runnable target
runnable target
runnable target
runnable target
runnable target
runnable target
runnable target
Jan 12, 2018 3:36:43 PM javaapplication1.JavaApplication1 lambda$main$1
runnable target
SEVERE: null
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at javaapplication1.JavaApplication1.lambda$main$1(JavaApplication1.java:27)
at java.lang.Thread.run(Thread.java:748)

Program 2

public class JavaApplication1 { 
    public static void main(String[] args) { 
        try { 
            Thread.sleep(2000); 
            boolean interrupted = Thread.interrupted(); 
            System.out.println(interrupted); 
            Thread currentThread = Thread.currentThread(); 
            System.out.println("Current Thread ID : " + currentThread.getId()); 
            System.out.println("State : " + currentThread.getState()); 
            
            Thread t = new Thread(() -> System.out.println("runnable target")); 
            System.out.println("Thread t not started yet : " + t.getState()); 
            System.out.println("Thread t not started yet : " + t.isAlive()); 
            System.out.println("T id : " + t.getId()); 
            
            Thread t2 = new Thread(() -> { 
                for (int i = 0; i < 10; i++) { 
                    try { 
                        System.out.println("runnable target"); 
                        if (i == 5) { 
                            System.out.println("t2 interrupted? "+Thread.interrupted()); 
                            System.out.println("State : "+currentThread.getState()); 
                            Thread.sleep(2000); 
                        } 
                    } catch (InterruptedException ex) { 
                        Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex); 
                    } 
                } 
            }); 
            t2.start(); 
            
            System.out.println("T id : " + t2.getId()); 
            System.out.println("default priority : " + t2.getPriority()); 
            
            System.out.println("interrupting the main thread---"); 
            currentThread.interrupt(); 
            System.out.println("Current Thread ID : " + currentThread.getId()); 
            System.out.println("State : " + currentThread.getState()); 
            System.out.println("is interrupted : " + currentThread.isInterrupted()); 
            
            System.out.println("interrupting the t2 thread---"); 
            t2.interrupt(); 
            System.out.println("Current Thread ID : " + t2.getId()); 
            System.out.println("State : " + t2.getState()); 
            System.out.println("is interrupted : " + t2.isInterrupted()); 
            
        } catch (InterruptedException ex) { 
            System.out.println("Interrupted Exception :" + ex); 
        } 
    } 
}

Program 2 输出

false
Current Thread ID : 1
State : RUNNABLE
Thread t not started yet : NEW
Thread t not started yet : false
T id : 10
T id : 11
default priority : 5
interrupting the main thread---
Current Thread ID : 1
State : RUNNABLE
State : true
interrupting the t2 thread---
Current Thread ID : 11
State : RUNNABLE
is interrupted : true
runnable target
runnable target
runnable target
runnable target
runnable target
runnable target
t2 interrupted? true
is interrupted : TERMINATED
runnable target
runnable target
runnable target
runnable target

三、用户的选择与疑惑

我选择了选项2和3,理由是:Program2中线程状态为TERMINATED,Program1中t2线程状态为RUNNABLE且抛出sleep中断异常。但我存在疑惑:如果t2线程状态是TERMINATED,为何末尾还打印了4次“runnable target”?线程处于TERMINATED状态难道不应该停止运行吗?


四、问题解答

1. 中断阻塞/睡眠线程的行为

当线程因sleep、join或wait进入阻塞状态时,调用其interrupt()方法会:

  • 立即清除线程的中断状态(注意:Thread.interrupted()会主动清除状态,而isInterrupted()仅查询不清除)
  • 抛出InterruptedException,让线程从阻塞状态退出,回到RUNNABLE状态,此时可以捕获异常并处理后续逻辑

2. 选择题正确选项分析

我们逐个拆解选项:

  • 选项1(进入非可运行状态):错误,中断的作用是让线程退出阻塞(非可运行)状态,而非进入。
  • 选项2(退出非可运行状态):正确,阻塞状态属于非可运行状态范畴,中断会触发线程从该状态退出。
  • 选项3(进入运行状态时抛出InterruptedException):正确,线程被中断后从阻塞中唤醒,此时处于RUNNABLE状态并抛出该异常。
  • 选项4(抛出异常后调用Thread.interrupted()返回true):错误,抛出InterruptedException时JVM会自动清除线程的中断状态,所以Thread.interrupted()会返回false(除非后续线程再次被中断)。
  • 选项5(以上都不是):错误,选项2和3均正确。

3. 关于Program2中TERMINATED状态却仍打印的疑惑

你看到的TERMINATED状态不是t2线程的,而是main线程的!仔细看Program2中t2的lambda代码:

System.out.println("State : "+currentThread.getState());

这里的currentThread是在main方法中初始化的Thread.currentThread(),它始终指向main线程,而非t2自身。

当t2执行到这行代码时,main线程可能已经执行完所有逻辑(main线程在调用t2.interrupt()后没有其他任务,很快就结束并进入TERMINATED状态)。而t2线程此时还在继续执行for循环的剩余迭代,所以会继续打印“runnable target”,直到循环完成10次后才会终止。


内容的提问来源于stack exchange,提问作者Dilini Peiris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:02:08