You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中实现任一FutureTask完成后终止另一任务的方法

解决方案

首先要注意:你当前使用的Executors.newSingleThreadExecutor()是单线程执行器,两个任务会串行执行,根本无法实现并行。第一步必须换成多线程线程池,比如Executors.newFixedThreadPool(2)。

要实现「一个任务完成就终止另一个」的逻辑,核心思路是:

  • 当任意一个任务执行完成时,立即调用另一个任务对应的Future.cancel(true)方法,向目标线程发送中断信号
  • 在method1()和method2()内部,定期检查当前线程的中断状态,一旦检测到中断,就停止执行并返回

修改后的完整代码

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;

public class Main {
    public static void main(String[] args) {
        try {
            // 换成多线程线程池,保证两个任务并行执行
            ExecutorService executor = Executors.newFixedThreadPool(2);
            
            // 用AtomicReference来保存两个Future,方便任务间互相访问
            AtomicReference<Future<Response>> future1Ref = new AtomicReference<>();
            AtomicReference<Future<Response>> future2Ref = new AtomicReference<>();

            // 任务1
            Callable<Response> task1 = () -> {
                Response response = method1();
                // 任务1完成后,立即取消任务2
                if (future2Ref.get() != null) {
                    future2Ref.get().cancel(true);
                }
                return response;
            };

            // 任务2
            Callable<Response> task2 = () -> {
                Response response = method2();
                // 任务2完成后,立即取消任务1
                if (future1Ref.get() != null) {
                    future1Ref.get().cancel(true);
                }
                return response;
            };

            // 提交任务并保存Future引用
            future1Ref.set(executor.submit(task1));
            future2Ref.set(executor.submit(task2));

            try {
                // 获取结果,任务被取消时会抛出CancellationException
                Response response1 = future1Ref.get().get();
                System.out.println("任务1完成,结果:" + response1.getMsg());
            } catch (CancellationException e) {
                System.out.println("任务1被取消");
            }

            try {
                Response response2 = future2Ref.get().get();
                System.out.println("任务2完成,结果:" + response2.getMsg());
            } catch (CancellationException e) {
                System.out.println("任务2被取消");
            }

            executor.shutdownNow(); // 关闭线程池
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static Response method1() {
        Response response = new Response();
        response.setMsg("test1");
        
        // 模拟耗时操作,期间定期检查中断状态
        try {
            for (int i = 0; i < 10; i++) {
                // 检查是否被中断,如果是则立即停止执行
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("method1检测到中断,提前返回");
                    return null;
                }
                Thread.sleep(500); // 模拟耗时步骤
            }
        } catch (InterruptedException e) {
            // 捕获中断异常,重置中断状态并返回
            Thread.currentThread().interrupt();
            System.out.println("method1被中断");
            return null;
        }
        
        return response;
    }

    private static Response method2() {
        Response response = new Response();
        response.setMsg("test2");
        
        // 模拟耗时操作,期间定期检查中断状态
        try {
            for (int i = 0; i < 5; i++) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("method2检测到中断,提前返回");
                    return null;
                }
                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("method2被中断");
            return null;
        }
        
        return response;
    }
}

class Response {
    String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

关键逻辑说明

  1. 线程池修正:使用newFixedThreadPool(2)保证两个任务能并行执行,这是实现需求的前提。
  2. 任务间的取消触发:每个任务执行完成后,通过AtomicReference获取另一个任务的Future,调用cancel(true)发送中断信号。
  3. method内部的中断检查:
    • 在耗时操作的循环中,定期调用Thread.currentThread().isInterrupted()检查中断状态,若已中断则提前返回。
    • 捕获InterruptedException(比如Thread.sleep()被中断时抛出),重置中断状态后返回,避免中断状态被吞噬。

注意事项

  • Future.cancel(true)只能向线程发送中断信号,无法强制终止线程,所以任务内部必须配合检查中断状态才能实现真正的终止。
  • 如果你的耗时操作是阻塞在某个IO调用上,需要确保该IO操作能响应中断(比如使用NIO而非传统阻塞IO),否则中断信号无法生效。

内容的提问来源于stack exchange,提问作者user_apr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 08:52:30