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();
}
posted @   QZero  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示