如何通过Java Future+线程池实现任务中止(附可运行代码)

目录

场景需求分析

技术实现方案

代码实现(SpringBoot示例)

总结


场景需求分析

在Web开发中常会遇到需要执行耗时操作的场景:

大数据量导出 复杂计算任务 第三方系统长时交互 文件批量处理等

当用户在前端触发任务后,如果中途希望终止执行,需要后端支持任务中断能力。

技术实现方案

核心流程图

sequenceDiagram
前端->>后端: 发起任务请求
后端->>线程池: 提交任务,获取Future
后端-->>前端: 返回任务ID
前端->>后端: 发送终止请求(携带任务ID)
后端->>Future: 执行cancel(true)
Future->>任务线程: 发送中断信号
任务线程-->>Future: 响应中断
后端-->>前端: 返回终止结果

代码实现(SpringBoot示例)

线程池配置

@Configuration
public class TaskConfig {
    
    @Bean("taskExecutor")
    public ExecutorService taskExecutor() {
        return Executors.newCachedThreadPool();
    }
}

任务管理服务

@Service
public class TaskService {
    
    private final ConcurrentMap<String, Future<?>> taskMap = new ConcurrentHashMap<>();
    
    @Autowired
    @Qualifier("taskExecutor")
    private ExecutorService executorService;

    // 提交任务并返回任务ID
    public String submitTask(String taskId, Runnable task) {
        Future<?> future = executorService.submit(task);
        taskMap.put(taskId, future);
        return taskId;
    }

    // 终止指定任务
    public boolean cancelTask(String taskId) {
        Future<?> future = taskMap.get(taskId);
        if (future != null && !future.isDone()) {
            return future.cancel(true); // 发送中断信号
        }
        return false;
    }

    // 清理已完成任务
    public void cleanup() {
        taskMap.entrySet().removeIf(entry -> entry.getValue().isDone());
    }
}

控制器实现

@RestController
@RequestMapping("/api/task")
public class TaskController {
    
    @Autowired
    private TaskService taskService;

    private static final AtomicLong taskIdCounter = new AtomicLong();

    @PostMapping("/start")
    public ResponseEntity<String> startTask() {
        String taskId = "TASK-" + taskIdCounter.incrementAndGet();
        
        taskService.submitTask(taskId, () -> {
            //业务处理
        });
        
        return ResponseEntity.ok(taskId);
    }

    @PostMapping("/cancel/{taskId}")
    public ResponseEntity<String> cancelTask(@PathVariable String taskId) {
        boolean success = taskService.cancelTask(taskId);
        return success ? 
            ResponseEntity.ok("任务已终止") : 
            ResponseEntity.status(404).body("任务不存在");
    }
}

中断响应机制

              注意: Future.cancel()这个方法只会发送中止信号,并不会直接中止线程,需要在业务代码主动检查线程的中止状态,并做对应的中止的业务处理

        1、协作式中断:Java 中断机制是协作式的,需主动检查状态

if (Thread.currentThread().isInterrupted()) {
    //检测到已被中止
    //执行对应的业务处理break、return等
}

        2、状态不可逆:一旦线程被中断,isInterrupted() 会持续返回 true,除非调用 Thread.interrupted() 清除状态。

        3、资源释放:在终止逻辑中需确保释放锁、关闭连接等操作。

        4、Future.cancel()原理

                future.cancel(true):发送中断信号

                future.cancel(false):仅取消未开始任务 返回true表示成功发送中断          

总结

通过合理使用Future和线程池,可以实现: 及时响应前端终止请求 有效释放服务器资源 避免无效计算

实际开发中需要特别注意对中断信号的正确处理,建议结合具体业务场景进行异常处理和资源清理的增强。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值