用completablefuture聚合多搜索引擎结果的核心是可控并行:各搜索源独立超时(ortimeout)、异常容错(exceptionally)、自定义线程池隔离,再通过allof+join安全聚合,最后按来源权重、去重、限流等业务逻辑增强结果。

用 CompletableFuture 聚合多个搜索引擎结果,核心是并行发起请求、统一收集响应、处理异常和超时。关键不在于“写完”,而在于“可控”——每个搜索源可独立失败、可设超时、结果可按需合并。
并行发起多个搜索请求
为每个搜索引擎(如百度、Google、Bing)创建一个独立的 CompletableFuture<list>></list>,用 supplyAsync 提交异步任务。务必指定自定义线程池,避免挤占 ForkJoinPool.commonPool():
- 定义线程池:
ExecutorService searchPool = Executors.newFixedThreadPool(5); - 每个搜索封装成 Supplier:
CompletableFuture<list>> baidu = CompletableFuture.supplyAsync(() -> searchBaidu(query), searchPool);</list> - 同理构建 google、bing 等,彼此完全解耦,互不影响
等待全部完成并安全聚合结果
用 CompletableFuture.allOf() 等待所有任务结束,但它返回 void,需手动提取结果。更推荐用 CompletableFuture.allOf(...).thenApply(...) 链式组合:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 先收集所有 future:
CompletableFuture<list>>[] futures = {baidu, google, bing};</list> - 组合等待与提取:
CompletableFuture.allOf(futures).thenApply(v -> Arrays.stream(futures).map(CompletableFuture::join).flatMap(List::stream).collect(Collectors.toList())) - 注意:
join()会阻塞当前 stage,但只在 allOf 触发后执行,不影响上游并行性
处理单个搜索失败或超时
不能让一个搜索引擎崩掉整个聚合。每个 future 应自带容错:
- 用
orTimeout(3, TimeUnit.SECONDS)设置单请求超时 - 用
exceptionally(ex -> Collections.emptyList())把异常转为空结果,避免传播中断整体流程 - 示例:
CompletableFuture.supplyAsync(..., pool).orTimeout(2, SECONDS).exceptionally(e -> { log.warn("Bing failed", e); return List.of(); })
按质量/时效合并去重与排序
原始结果只是列表拼接,需业务逻辑增强:
- 去重:用 URL 或标题哈希做唯一标识,
Collectors.toMap(urlExtractor, Function.identity(), (a,b) -> a) - 加权排序:给不同来源打分(如 Google 权重 1.2,Bing 0.9),再按分数+时间戳综合排序
- 限制总数:最后用
.limit(20)防止结果爆炸,保持响应轻量
整个过程不依赖外部框架,纯 JDK 异步组合,灵活且易测。重点是把“每个搜索”当作可插拔单元,失败不传染、超时不拖累、结果可裁剪。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










