java线程池的一个小坑:shutdown之后线程并不会停止运行
问题背景
最近我想要实现一个这样的功能:在线程运行超过一段时间之后就向主程序抛出一个异常,并停止这个线程。
其具体的应用场景是一个任务由多个子任务组成,每个子任务单独一个线程,如果某个子任务长时间未完成就认为这个子任务失败(可能是因为网络原因卡死了),就需要把这个线程结束掉,然后等待调度器重新运行这个子任务。
(java的任何网络请求都可能会出现永久卡死的情况,这个一定要考虑到!!)
最初的解决方案及问题
最开始我们参考了网上最常见的解决办法,就是使用ExecutorService+Future,使用Future类的get方法来实现。但是后面实际部署上去之后发现,线程超时的异常被截获到了,但是线程依然在运行。
即使是使用了future.cancel和executorService.shutdown,正在运行的线程也不会停止,可以通过以下的示例代码来验证:
ExecutorService executorService= Executors.newSingleThreadExecutor();
Future<Object> future=executorService.submit(()->{
while (true){
try {
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("Test");
}
// return null;
});
try {
Object ret=future.get(3, TimeUnit.SECONDS);
System.out.println("Got it");
}catch (Exception e){
while(!future.cancel(false)){
System.out.println("Cancel failed");
}
System.err.println("Error "+future.isCancelled());
e.printStackTrace();
}finally {
executorService.shutdown();
}
修改后的解决方案
个人推测应该是不存在可以强行停止线程的api,我们能做的只能是使用一个flag让线程自己停止运行,这个flag可以考虑使用executorService.isShutdown(),这个具体怎么做就得具体问题具体分析了,以下是修改后的示例代码:
ExecutorService executorService= Executors.newSingleThreadExecutor();
Future<Object> future=executorService.submit(()->{
while (!executorService.isShutdown()){
try {
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("Test");
}
return null;
});
try {
Object ret=future.get(3, TimeUnit.SECONDS);
System.out.println("Got it");
}catch (Exception e){
while(!future.cancel(false)){
System.out.println("Cancel failed");
}
System.err.println("Error "+future.isCancelled());
e.printStackTrace();
}finally {
executorService.shutdown();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗