interrupt
interrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。
注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态并做处理。
如果目标线程当前正在执行某些可能阻塞的操作(如
Thread.sleep()
, Object.wait()
, 或者 I/O 操作等),那么调用 interrupt()
会使得这些方法抛出 InterruptedException
.interrupted 和 isInterrupted
interruptted实现:
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
该方法就是直接调用当前线程的isInterrupted(true)方法。
isInterrupted实现:
public boolean isInterrupted() {
return isInterrupted(false);
}
这两个方法有两个主要区别:
- interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。)
- 这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false;
第二个区别主要体现在调用的方法的参数上,让我们来看一看这个参数是什么含义
先来看一看被调用的方法 isInterrupted(boolean arg)的定义:
private native boolean isInterrupted(boolean ClearInterrupted);
原来这是一个本地方法,看不到源码。通过参数名我们就能知道,这个参数代表是否要清除状态位。
如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位。这个参数为false,就是直接返回线程的状态位。
也就是interrupted返回线程的状态位,又清空了状态位。isInterrupted只是返回了线程的状态位。
以下程序看这三个方法的区别:
public class ThreadInterruptTest {
public static void main(String[] args) {
System.out.println("isInterrupted :" + Thread.currentThread().isInterrupted());//当前线程没有被中断,返回false;
Thread.currentThread().interrupt();//中断了该线程,但是该线程仍会继续执行,该方法只是将线程的状态设置成“中断”状态
System.out.println("isInterrupted :" + Thread.currentThread().isInterrupted());//interrupt()执行后,线程被设置成中断状态,返回true
System.out.println("interrupted :" + Thread.interrupted());//返回了中断状态:true,又清掉了状态位。
System.out.println("isInterrupted :" + Thread.currentThread().isInterrupted());//由于interrupted()清掉了状态位,所以返回false;
System.out.println("interrupted :" + Thread.interrupted());//返回false
}
}
执行结果:
InterruptedException
当一个线程被一些声明了InterruptedException的方法阻塞时,你对这个线程调用Thread.interrupt(),那么大多数这样的方法会立即抛出InterruptedException.如果有些人试着去打断我们的线程,而我们通过捕捉InterruptedException发现了它,这时候最合理的事情就是结束上述被打断的线程(然而大多数时候我们并不处理它)。
public class InterruptedExceptionTest {
public static void main(String[] args) throws InterruptedException {
ThreadA a = new ThreadA();
a.start();
Thread.sleep(2000);
a.interrupt();
System.out.println("a:" + a.isInterrupted());
}
}
class ThreadA extends Thread {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("正在执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {//状态位被清除
e.printStackTrace();
System.out.println("该线程:" + Thread.currentThread().isInterrupted());//由于状态位被清除,返回false
Thread.currentThread().interrupt();
}
}
}
}
上面的程序中,主线程调用了a线程的interrupt()方法(线程a的状态位被置为"中断"),线程a捕获了InterruptedException后(此时,线程a的“中断”状态被清除),调用了Thread.currentThread().interrupt(),线程a的状态被置为“中断”,接着继续执行循环条件,线程是中断状态,跳出了循环,线程最终结束了执行。这里,如果在捕获InterruptedException后,不将线程的状态置为“中断”,那么循环仍然会执行,并不会结束。
注意一下几点:
- 捕获InterruptedException之后应该适当地对它进行处理-大多数情况下适当的处理指的是完全地跳出当前任务/循环/线程。
- 吞掉InterruptedException不是一个好主意
- 如果线程在非阻塞调用中被打断了,这时应该使用isInterrupted()。当线程早已被打断(也就是被标记为interrupted)时,一旦进入阻塞方法就应该立刻抛出InterruptedException。