一直不明白为什么Thread.sleep(long millis)方法为啥会抛出checked异常InterruptedException,在网上找到了一篇非常好的文章《Java 理论与实践: 处理 InterruptedException》,以下主要是通过代码来逐一说明这篇几个关键的要点。
线程中断的标志
其实
Thread类中维护这一个状态变量还表示线程是否已中断,我们可以通过
isInterrupted()方法返回该线程的中断状态。另外Thread还提供了一个静态方法
interrupted()同样能返回该线程的中断状态,不过调用该方法将导致Thread的中断状态被清除(即重置为默认值false)。
阻塞方法
在上述文章
《Java 理论与实践: 处理 InterruptedException》说明了阻塞方法的概念,并说明了阻塞方法抛出
InterruptedException其实是一种线程的可取消机制。
非阻塞方法的中断处理
若线程运行的任务是非阻塞的,则调用线程的interrupt()方法并不会的导致线程中断,该方法作用其实是改变线程的中断标志。
public static void test1() throws InterruptedException {
//未对中断状态进行处理,该线程并不会中断
Thread thread = new Thread() {
private int i = 0;
public void run() {
while (true) {
i++;
System.out.println(i);
}
};
};
thread.start();
Thread.sleep(1000);
System.out.println(thread.isInterrupted()); // 输出false
thread.interrupt();//中断线程
System.out.println(thread.isInterrupted()); // 输出true
}
要让该线程支持中断机制应只需做如下修改
Thread thread = new Thread() {
private int i = 0;
public void run() {
//检查线程的中断状态
while (!isInterrupted()) {
i++;
System.out.println(i);
}
};
};
阻塞方法的中断处理:处理InterruptedException
如果抛出
InterruptedException意味着一个方法是阻塞方法,那么调用一个阻塞方法则意味着您的方法也是一个阻塞方法,而且您应该有某种策略来处理
InterruptedException。
通过查看官方的API文档,我们可以知道
Thread方法
sleep(long millis) throws InterruptedException有如下说明:
(1)当线程调用sleep()方法进入阻塞状态后,如果任何线程中断了该线程,将抛出
InterruptedException异常。
(2)抛出
InterruptedException异常后,当前线程的中断状态将被清除(即重置为默认值false)
public static void test1() throws InterruptedException {
Thread thread_A = new Thread() {
private int i = 0;
public void run() {
//该循环不会终止
while (!isInterrupted()) {
i++;
System.out.println(i);
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(isInterrupted()); //中断状态被清除,输出false
}
}
};
};
thread_A.start();
Thread.sleep(1000);
//中断线程A,这时候线程A正处于阻塞状态,将抛出InterruptedException
thread_A.interrupt();
}
不得不说我们大多数做法就是生吞
InterruptedException,良好的编程习惯应当要视情况对该异常做一些处理,如对上述代码做如下修改
Thread thread_A = new Thread() {
private int i = 0;
public void run() {
while (!isInterrupted()) {
i++;
System.out.println(i);
try {
sleep(5000);
} catch (InterruptedException e) {
interrupt(); //恢复设置成中断状态
}
}
};
};
上述仅仅对 Thread的 sleep()方法作出说明,还有很多方法同样会抛出 InterruptedException。正确的做法是先认真看其API说明文档,避免生吞了该异常。