Java-interrupt方法的一个小的注意点
Java-interrupt方法的一个小的注意点
记录Java 中 interupt()
方法的一个小的知识点。
开发过程中,经常有需要去终止线程,终止线程的方式无外乎有两种 标志位 或 interrupt(), 前者没什么好说的,就是定义一个bool类型的变量,只是需要注意将该变量声明成 volatile
。后者的话主要用于终止带阻塞状态的线程,当然也可以用来终止不带阻塞状态的线程,这里再来复习一下:
关于终止线程的介绍,可参考:Java: Java终止线程的几种方式
终止不带阻塞状态的线程
TaskCase.java
package com.yongdaimi.dmeo;
public class TaskCase {
private Thread mTaskThread;
public void start() {
mTaskThread = new Thread() {
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName()+" start running...");
// 模拟重复执行的任务
while (!Thread.currentThread().isInterrupted()) {
System.out.println("doSomething");
}
System.out.println(Thread.currentThread().getName()+" stop running...");
}
};
mTaskThread.start();
}
/**
* 使用此方法进行终止
*/
public void calcel() {
mTaskThread.interrupt();
}
}
Test.java
package com.yongdaimi.dmeo;
public class Test {
public static void main(String[] args) {
TaskCase task = new TaskCase();
task.start();
// 2s 后将测试线程终止
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
task.calcel();
}
}
运行:
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
Thread-0 stop running...
可以看到使用此方法,2秒后是可以将执行线程正常终止的。
那如果加了阻塞状态呢?
TaskCase.java
package com.yongdaimi.dmeo;
public class TaskCase {
private Thread mTaskThread;
public void start() {
mTaskThread = new Thread() {
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName()+" start running...");
// 模拟重复执行的任务
while (!Thread.currentThread().isInterrupted()) {
System.out.println("doSomething");
// 模拟阻塞 500ms
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" stop running...");
}
};
mTaskThread.start();
}
/**
* 使用此方法进行终止
*/
public void calcel() {
mTaskThread.interrupt();
}
}
这里在线程中添加一段code, 使线程临时阻塞500ms, 再次执行:
这时发现虽然有走到异常的代码块里,但是线程仍然能够正常执行,没有退出,Why? 这是因为:
「注意:发生异常时线程的中断标志为会由true更改为false。」
所以最好这样写成这样:
// 模拟重复执行的任务
while (!Thread.currentThread().isInterrupted()) {
System.out.println("doSomething");
// 模拟阻塞 500ms
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
// 重置中断标志位为true
Thread.currentThread().interrupt();
}
}
在出现异常后,重置中断标志位,这样再次执行后,就可以顺利中断线程了:
当然也可以在出现异常时,直接使用return语句终止,那样也是可以的,今天在是review一个同事的code时发现了此问题,所以记录一下。
参考链接:
为什么说volatile+interrupt是停止线程最优雅的姿势?
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2019-12-09 Fragment: 使用newInstance()来实例化fragment(转)
2019-12-09 Java: 线程池(ThreadPoolExecutor)中的参数说明