异步编程CompletionService

CompletionService 是 Java 并发包(java.util.concurrent)里的一个 "异步结果收割机"

它把「提交任务」和「拿结果」两件事解耦:

你只管往里扔任务;它帮你盯着谁先跑完,让你 按完成顺序 取结果,而不是按提交顺序。


一、核心 API(就 4 个常用方法)

方法 作用
submit(Callable/Runnable) 扔一个任务进去
take() 阻塞 直到有任务完成,返回完成的 Future
poll() 立刻返回,如果没有已完成的任务返回 null
poll(timeout, unit) 等指定时间,超时返回 null

二、使用套路(3 步曲)

  1. 创建线程池 + CompletionServic

    复制代码
    ExecutorService pool = Executors.newFixedThreadPool(4);
    CompletionService<String> cs = new ExecutorCompletionService<>(pool);
  2. 批量提

    复制代码
    for (int i = 0; i < 10; i++) {
        final int no = i;
        cs.submit(() -> {
            Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 3000));
            return "task-" + no;
        });
    }
  3. 按完成顺序收割

    复制代码
    for (int i = 0; i < 10; i++) {
        String result = cs.take().get();   // 谁先跑完谁先拿到
        System.out.println(result);
    }
    pool.shutdown();

三、场景举例

  • 并发下载:10 张图片同时开线程下,下好一张立刻显示一张,不用等全部下完。

  • 并发调用多服务:A、B、C 三个微服务都查一遍,谁返回快就用谁的数据。

  • 并行计算:跑 100 个 Monte-Carlo 任务,每算完一个就汇总,不用等全部结束再统计。


四、对比"裸用 FutureList"

方式 拿结果顺序 是否阻塞
List<Future> 按提交顺序 会卡在还没跑完的任务
CompletionService 按完成顺序 只阻塞在 take(),总有结果就返回

五、完整可运行 Demo

复制代码
import java.util.concurrent.*;
public class Demo {
    public static void main(String[] args) throws Exception {
        ExecutorService pool = Executors.newFixedThreadPool(4);
        CompletionService<Integer> cs = new ExecutorCompletionService<>(pool);

        // 1. 提交 5 个耗时不一样的任务
        for (int i = 1; i <= 5; i++) {
            final int sec = i;
            cs.submit(() -> {
                TimeUnit.SECONDS.sleep(sec);
                return sec;
            });
        }

        // 2. 按完成顺序打印
        for (int i = 0; i < 5; i++) {
            Integer who = cs.take().get();
            System.out.println("任务 " + who + " 秒完成!");
        }
        pool.shutdown();
    }
}

运行结果(每次都一样):

任务 1 秒完成!

任务 2 秒完成!

任务 3 秒完成!

任务 4 秒完成!

任务 5 秒完成!


一句话总结:
CompletionService = 线程池 + 优先队列 ,让你 先做完的先拿走,写并行流水线最舒服。

相关推荐
big狼王4 分钟前
SonarQube本地化搭建及代码检测并导出报告PDF
java·pdf·sonarqube·sonarscanner
杨筱毅5 分钟前
【Android】Handler/Looper机制相关的类图和流程图
android·java·流程图
SimonKing6 分钟前
【开发者必备】Spring Boot 2.7.x:WebMvcConfigurer配置手册来了(二)!
java·后端·程序员
DokiDoki之父16 分钟前
Spring—容器
java·后端·spring
一个龙的传说16 分钟前
springboot优雅停止的流程梳理
java·spring boot·rpc
搬砖的工人1 小时前
记录WinFrom 使用 Autoupdater.NET.Official 进行软件升级更新
java·前端·.net
努力进修1 小时前
【JavaEE初阶】 多线程编程核心:解锁线程创建、方法与状态的创新实践密码
android·java·java-ee
xiezhr1 小时前
见过哪些醍醐灌顶的Java代码:从"卧槽"到"原来如此"的顿悟
java·后端·设计模式
当战神遇到编程1 小时前
数组的定义与使用
java·idea
三角叶蕨1 小时前
Redis极简入门 整合springboot
java·redis