「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」
Hope is a good thing, maybe the best of things. And no good thing ever dies—— 《The Shawshank Redemption》
前言
Java 本身的概念还是比较多的,所以学习的开始还是要先打好基础,从一些基本的概念入手,这些都是Java的一些常识。在Java的面试中都是很重要的东西。
上一篇内容我们学习了几种线程的终止方式,今天就来聊一聊一种很常见的中断方式:被中断异常(Interrupt Exception)
什么是被中断异常?
我们先查看一下 interrupt() 方法的源码,在其源码的注释中的第二段是这样解释的:
* <p> If this thread is blocked in an invocation of the {@link
* Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
* Object#wait(long, int) wait(long, int)} methods of the {@link Object}
* class, or of the {@link #join()}, {@link #join(long)}, {@link
* #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
* methods of this class, then its interrupt status will be cleared and it
* will receive an {@link InterruptedException}.
从上面的注释我们可以看到,当我们的主线程调用 interrupt() 方法去终止线程的时候,如果子线程被 wait()、join()或者sleep(long)阻塞的时候,它的中断状态将会被清空,同时还可以得到一个 InterruptedException,此时我们的中断状态就被重置为false。看到这里,我们可以想一下,既然它可以跑出异常,那么我们就可以在它的异常中去中断它的程序。
被中断异常的常见方式
上面我们提到了,
当此方法尝试中断一个处于阻塞状态的线程时,该线程会抛出一个异常 InterruptedException,并将此线程的中断状态,清除为false。所以当子线程处于阻塞状态的时候,我们又想程序能够继续响应它的中断状态,那么我们可以在 catch 中重新中断程序即可。
阻塞状态的代码如下:
package stop;
public class InterruptThread {
public static void main(String[] args) {
Runnable runnableThreadImp = () -> {
Thread currentThread = Thread.currentThread();
while (!currentThread.isInterrupted()) {
// 清楚当前线程的中断状态为false,以便响应其它的情况
// while (!Thread.interrupted() /* && 其它条件 */) {
// System.out.print("Runnable-Thread" + "\n");
System.out.println("Runnable-Thread");
// TODO 清理工作
try {
/***** 此处阻塞子程序 *****/
Thread.sleep(200); // 让子线程休眠200毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread runnable = new Thread(runnableThreadImp);
runnable.start();
try {
Thread.sleep(5); // 让主线程休眠20ms
} catch (InterruptedException e) {
e.printStackTrace();
}
// 请求中断线程,即设置当前线程的中断状态为true
// 当此方法尝试中断一个处于阻塞状态的线程时,该线程会抛出一个异常 InterruptedException
// 并将此线程的中断状态,清除为false
runnable.interrupt();
}
}
从上图可以看出,程序会抛出一个java.lang.InterruptedException: sleep interrupted 的异常。
我们在得到异常的时候再去重新调用 interrupt() 方法去中断程序。
package stop;
public class InterruptThread {
public static void main(String[] args) {
Runnable runnableThreadImp = () -> {
Thread currentThread = Thread.currentThread();
while (!currentThread.isInterrupted()) {
// 清楚当前线程的中断状态为false,以便响应其它的情况
// while (!Thread.interrupted() /* && 其它条件 */) {
// System.out.print("Runnable-Thread" + "\n");
System.out.println("Runnable-Thread");
// TODO 清理工作
try {
Thread.sleep(200); // 让子线程休眠200毫秒
} catch (InterruptedException e) {
// e.printStackTrace();
/**** 调用 interrupt() 方法去中断程序 ****/
currentThread.interrupt();
}
}
};
Thread runnable = new Thread(runnableThreadImp);
runnable.start();
try {
Thread.sleep(5); // 让主线程休眠20ms
} catch (InterruptedException e) {
e.printStackTrace();
}
// 请求中断线程,即设置当前线程的中断状态为true
// 当此方法尝试中断一个处于阻塞状态的线程时,该线程会抛出一个异常 InterruptedException
// 并将此线程的中断状态,清除为false
runnable.interrupt();
}
}
看上图的执行效果,我们可以看得出在catch 中重新执行currentThread.interrupt()是可以正常的中断程序的。
结语
如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。
文章如有错误之处,希望在评论区指正🙏🙏
欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后 」