Java 线程池取消的方式

Java 线程池取消的方式

  • 线程池取消分为取消线程池中单个任务和关闭线程池本身,过程分为停止接收新任务、终止正在执行的任务以及清理未执行的任务

Future#cancel 取消单个任务

java 复制代码
public static void main(String[] args) {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Future<?> future = executor.submit(() -> {
        try {
               while (!Thread.currentThread().isInterrupted()) {
                   //执行任务逻辑
               }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); //重设中断状态
        }
    });
    //演示逻辑
    try {
        //等待一段时间后去中断 thread 线程
        Thread.sleep(10);
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("请求线程取消");
    //true 尝试中断正在执行的任务(依赖任务本身是否处理中断,任务内部​需要有响应中断的逻辑),false 仅取消未开始执行的任务(不会中断正在运行的任务,会继续工作)
    boolean cancelled = future.cancel(true); //FutureTask#cancel 传 true 内部会调用 Thread#interrupt 方法
    System.out.println("任务是否取消成功:" + cancelled);
    //
    executor.shutdown();
}

shutdown 平滑关闭

  • 停止接收新任务,会等待已提交的任务(包括正在执行的和队列中等待的)执行完成后再关闭
  • 可以确保已提交的任务都是正常结束的
java 复制代码
//停止接收新任务,等待已提交任务完成
executor.shutdown();

shutdownNow 强制关闭

  • 内部会调用 Thread#interrupt 方法,能否通过 interrupt 有效取消任务,取决于任务本身响应中断的逻辑
  • 停止接收新任务,尝试立即关闭线程池,返回尚未执行的任务列表,并尝试中断正在执行的任务
  • 后续可以对尚未执行的任务进行处理,比如记录日志或重新提交
java 复制代码
//立即停止所有任务,返回未执行的任务列表
List<Runnable> cancelledTasks = executor.shutdownNow();
System.out.println("被取消的任务数: " + cancelledTasks.size());

线程池关闭最佳实践

java 复制代码
private void executorShutdown() {
    if (executor.isShutdown()) { //判断线程池是否已调用 shutdown 或 shutdownNow 过了
        return;
    }
    executor.shutdown(); //触发关闭,停止接收新任务,等待已提交任务完成
    try {
        //最多等待 30 秒,尽量能够让已提交任务执行完成
        if (!executor.awaitTermination(30, TimeUnit.SECONDS)) { //awaitTermination 会阻塞当前线程等待线程池关闭
            //超时后强制关闭
            executor.shutdownNow();
            //再次等待(可选)
            if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
                System.err.println("线程池未完全终止");
            }
        }
    } catch (InterruptedException e) {
        //处理中断(如果当前线程在 awaitTermination 等待期间被其他线程调用 Thread#interrupt 方法中断)
        executor.shutdownNow();
        Thread.currentThread().interrupt(); //重设中断状态
    }
}

总结

  • 任务响应中断:使用 Future.cancel(true) 或 shutdownNow 时,任务自身需要通过 Thread.currentThread().interrupted() 或InterruptedException 检测中断状态并响应中断
  • 优先使用 shutdown 仅在必要时使用 shutdownNow
相关推荐
Billy_Zuo2 小时前
人工智能机器学习——模型评价及优化
android·人工智能·机器学习
tangweiguo030519873 小时前
Flutter与原生混合开发:实现完美的暗夜模式同步方案
android·flutter
雨白4 小时前
深入理解 Android 触摸事件:以实现 ViewPager 为例
android
shenshizhong4 小时前
看懂鸿蒙系统源码 比较重要的知识点
android·harmonyos
一只修仙的猿5 小时前
再谈性能优化,一次项目优化经历分享
android·性能优化
雮尘7 小时前
Android性能优化之枚举替代
android
2501_915909069 小时前
苹果上架App软件全流程指南:iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传与审核技巧详解
android·ios·小程序·https·uni-app·iphone·webview
2501_915921439 小时前
iOS 文件管理与能耗调试结合实战 如何查看缓存文件、优化电池消耗、分析App使用记录(uni-app开发与性能优化必备指南)
android·ios·缓存·小程序·uni-app·iphone·webview
2501_9159184110 小时前
App 苹果 上架全流程解析 iOS 应用发布步骤、App Store 上架流程
android·ios·小程序·https·uni-app·iphone·webview