由易到难开始介绍吧
isInterrupted
最容易理解的,查看线程是否被打断,没有副作用。可以自己询问自己,也可以在A线程中询问B线程。
Thread A = new Thread(() -> {
//自己询问自己
Thread.currentThread().isInterrupted();
},"A");
A.start();
Thread B = new Thread(() -> {
//在B中询问A
A.isInterrupted();
},"B");
B.start();
interrupt
最复杂的一个,分为几种情况:
- 如果线程此时正在InterruptibleChannel上执行I/O操作,线程的打断状态被设置为true,抛出异常
- 如果线程此时正被Selector阻塞,线程的打断状态被设置为true,线程立即返回一个非零值。
- 如果线程此时正被sleep、wait、join(包括这些函数带参数的版本)阻塞着呢,线程的打断状态被重置,即设为false,再抛出InterruptedException。这意味着如果在捕获InterruptedException的逻辑中不能通过isInterrupted或者interrupted来正确判断线程是否被打断,因为打断状态已经被重置了。
- 其他情况,打断状态被设置为true。
注意 第一和第二都是与管道I/O相关的,平时都接触不到。当读取File时被打断不会抛出异常。
接下来演示第三和第四种情况
class Demo {
static boolean flag = true;
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
final Thread a = new Thread(() -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + "获得了锁");
try {
flag = false;
lock.wait();
} catch (InterruptedException e) {
//符合第三种情况,虽然a被b打断了,但这里返回的是false,即打断状态被重置了。
System.out.println("a捕获InterruptedException异常后Thread.currentThread().isInterrupted() " + Thread.currentThread().isInterrupted());
e.printStackTrace();
}
}
}, "a");
a.start();
while (flag){}//保证a线程先于b线程执行
new Thread(() -> {
synchronized (lock) {
//此时a线程还没有被打断,isInterrupted返回false,没有副作用
System.out.println("b第一次询问a.isInterrupted() " + a.isInterrupted());
//在b线程中打断a线程
a.interrupt();
//此时a线程被打断,isInterrupted返回true,没有副作用
System.out.println("b第二次询问a.isInterrupted() " + a.isInterrupted());
//没有阻塞的情况下打断线程,符合第四种情况,只是把打断状态设置为true
Thread.currentThread().interrupt();
System.out.println("b自我打断之后Thread.currentThread().interrupt() " + Thread.interrupted());
lock.notify();
}
}, "b").start();
}
}
结果如下图:
看一个读取文件的例子:
interrupted
最让人疑惑的一个。因为他又副作用。就是会重置线程的打断状态,即设置为false。可想而知,如果一个线程被interrupt了,再 马上连续多次 通过Thread.interrupted()查看,只有第一次是true,以后就是false。而isInterrupted不管调用几次都不会有副作用。
注意文中的 马上连续多次 ,要求多次Thread.interrupted()之间不能再被interrupt
Thread.currentThread().interrupt();
//连续多次调用Thread.interrupted()
System.out.println(Thread.interrupted());//true,打断状态被重置为false
System.out.println(Thread.interrupted());//false
Thread.currentThread().interrupt();
System.out.println(Thread.interrupted());//true
Thread.currentThread().interrupt();
System.out.println(Thread.interrupted());//true
总结
- 打断别人用a.interrupt();
- 打断自己用Thread.currentThread().interrupt();
- 查看别人的打断状态用a.isInterrupted();
- 查看自己的打断状态用Thread.currentThread().isInterrupted();
参考
作者:大闲人柴毛毛
链接:https://www.zhihu.com/question/41048032/answer/252905837
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。