异步编程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 = 线程池 + 优先队列 ,让你 先做完的先拿走,写并行流水线最舒服。

相关推荐
一定要AK14 分钟前
Spring 入门核心笔记
java·笔记·spring
A__tao15 分钟前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
KevinCyao29 分钟前
java视频短信接口怎么调用?SpringBoot集成视频短信及回调处理Demo
java·spring boot·音视频
迷藏49435 分钟前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
wuxinyan1232 小时前
Java面试题47:一文深入了解Nginx
java·nginx·面试题
新知图书2 小时前
搭建Spring Boot开发环境
java·spring boot·后端
冰河团队2 小时前
一个拉胯的分库分表方案有多绝望?整个部门都在救火!
java·高并发·分布式数据库·分库分表·高性能
洛_尘2 小时前
Java EE进阶:Linux的基本使用
java·java-ee
宸津-代码粉碎机2 小时前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
MaCa .BaKa2 小时前
47-心里健康咨询平台/心理咨询系统
java·spring boot·mysql·tomcat·maven·intellij-idea·个人开发