1,概述
首先,线程的中断是一种协作机制,什么是协作机制呢?每个线程都有一个boolean类型的中断状态,其他线程通过修改该线程的中断状态来控制该线程的中断;当中断时,会继续完成当前的线程任务。
2,Thread中断方法
interrupt():设置中断
isInterrupted():是否中断(返回是否已经设置中断状态)
interrupted():清除调用方当前线程的中断状态(静态方法)
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
3,线程中断测试
class ThreadInterruptDemo {
public static void main(String[] args) {
System.out.println("进入测试");
Thread thread = new Thread(() -> {
Thread.currentThread().interrupt();
System.out.println("线程中断 <- thread");
System.out.println("thread.isInterrupted()=" + Thread.currentThread().isInterrupted() + " <- thread");
int count = 0;
while (true) {
if (!Thread.currentThread().isInterrupted()) {
System.out.println("取消中断状态 <- thread");
} else {
System.out.println("中断状态 <- thread");
}
count++;
if (count == 1) {
boolean interrupted = Thread.interrupted();
System.out.println("通过interrupted()清空中断状态=" + interrupted + " <- thread");
}
if (count == 2) {
break;
}
}
});
thread.start();
System.out.println("结束测试");
}
}
由此可见,
- 线程中断后,程序会继续完成当前任务,而且当任务完成后不会再开起程序;
- 通过
Thread.interrupted()
方法是可以清除线程的中断状态的;
4,测试中遇到的问题
在main函数中调用Thread.interrupted()
时,子线程一直没有清除中断状态;
答:经过查看代码之后,发现了interrupted()方法的原理为调用当前线程的取消中断,且为静态方法,所以只能在当前线程中调用才能清除本线程的中断状态;
5,InterruptedException异常处理解析
部分阻塞线程的注释如下:
InterruptedException – if any thread interrupted the current thread before or while the current thread was waiting. The interrupted status of the current thread is cleared when this exception is thrown.
InterruptedException
异常的注释:
The following code can be used to achieve this effect:
if (Thread.interrupted()) // Clears interrupted status! throw new InterruptedException();
当抛出InterruptedException
异常时,中断状态将被清除;因此当通过try/catch
捕获异常但不处理异常,就会造成线程继续执行,而不会按照原有的设想继续中断的情况;不过可以通过捕获异常来处理线程阻塞但需要中断的程序;具体如下:
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100000); // 线程在此处阻塞,通过interrupt调用此线程中断
} catch (InterruptedException e) {
System.err.println("沉睡中被中断,且中断被清除");
}
//线程将继续执行
System.err.println(Thread.currentThread().isInterrupted());
}
}
可以通过如下方法传递中断:
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100000);// 线程在此处阻塞,通过interrupt调用此线程中断
} catch (InterruptedException e) {
System.err.println("沉睡中被中断,且中断被清除");
//传递中断
Thread.currentThread().interrupt()
}
//中断状态
System.err.println(Thread.currentThread().isInterrupted());
}
}
且当线程已经处于中断状态时,Thread.sleep()
会直接抛出异常
@Override
public void run() {
Thread.currentThread().interrupt();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
//当前线程已处于中断状态,会直接抛出异常
}
}