CompletableFuture 异步任务竞速条件取消

package com.demo.data;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

public class EitherCancelAllDemo {

    static boolean isEmptyOrZero(Integer v) {
        return v == null || v == 0;
    }

    public static void main(String[] args) throws Exception {
        ExecutorService pool = Executors.newFixedThreadPool(4);
        try {
            List<CompletableFuture<Integer>> futures = Arrays.asList(
                    CompletableFuture.supplyAsync(() -> run("A", 3000, 42), pool),
                    CompletableFuture.supplyAsync(() -> run("B", 2000, 7), pool),
                    CompletableFuture.supplyAsync(() -> run("C", 1000, 0), pool),   // 这个会触发取消
                    CompletableFuture.supplyAsync(() -> run("D", 4000, 99), pool));

            AtomicBoolean cancelled = new AtomicBoolean(false);
            for (CompletableFuture<Integer> f : futures) {
                f.whenComplete((res, ex) -> {
                    if (ex == null && isEmptyOrZero(res)) {          // 任一任务结果空/0
                        if (cancelled.compareAndSet(false, true)) {  // 只触发一次
                            System.out.println("发现空/0 结果,取消所有任务");
                            futures.forEach(other -> other.cancel(true)); // 已完成的 cancel 无副作用
                        }
                    }
                });
            }

            try {
                // 等齐所有任务;任一被取消/异常则整体失败
                CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
                List<Integer> results = futures.stream()
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList());
                if (results.stream().anyMatch(EitherCancelAllDemo::isEmptyOrZero)) {
                    // 兜底:后完成者返回空/0(对方已完成,来不及打断)
                    System.out.println("存在空/0 结果(后完成者),整体失败: " + results);
                } else {
                    System.out.println("全部有效,等齐完成: " + results);
                }
            } catch (CancellationException e) {
                System.out.println("某任务结果为空/0,已打断全部,整体失败");
            }
        } finally {
            pool.shutdownNow();
            pool.awaitTermination(5, TimeUnit.SECONDS);
        }
    }

    static Integer run(String name, int millis, int result) {
        try {
            for (int i = 0; i < millis / 100; i++) {
                Thread.sleep(100);
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println(name + " 收到中断,提前退出");
                    return null;
                }
            }
            System.out.println(name + " 完成,结果=" + result);
            return result;
        } catch (InterruptedException e) {
            System.out.println(name + " 被中断,退出");
            return null;
        }
    }
}
posted @ 2026-08-27 09:26  lyu6  阅读(3)  评论(0)    收藏  举报