news 2026/4/16 14:20:03

详细分析Java8中的CompletableFuture异步编程类(附Demo)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
详细分析Java8中的CompletableFuture异步编程类(附Demo)

目录

  • 前言
  • 1. 基本知识
  • 2. Demo
  • 3. 实战

前言

Java基本知识:

  1. java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
  2. 【Java项目】实战CRUD的功能整理(持续更新)

1. 基本知识

CompletableFuture 是 Java 8 引入的异步编程类,属于 java.util.concurrent 包的一部分

  1. 异步计算(async computation)

  2. 事件驱动(callback)

  3. 任务组合(composition)

  4. 异常处理(exception handling)

核心思想是非阻塞地执行任务,并在任务完成后处理结果

核心特性

  • 非阻塞:与 Future.get() 阻塞不同,CompletableFuture 可以通过回调非阻塞地处理结果

  • 链式调用:可以通过方法链组合多个异步任务

  • 异常处理:提供 exceptionally、handle 等方法处理异常

  • 线程池支持:可以指定 Executor 来控制异步任务执行线程

常用的方法总结如下:

方法类型功能描述注意事项
runAsync(Runnable)创建异步执行无返回值任务默认使用 ForkJoinPool.commonPool(),任务无返回值
supplyAsync(Supplier<U>)创建异步执行有返回值任务默认使用 ForkJoinPool.commonPool()
thenApply(Function<? super T,? extends U>)转换对结果进行处理并返回新值上一个任务异常时不执行
thenAccept(Consumer<? super T>)消费对结果进行消费,无返回值上一个任务异常时不执行
thenRun(Runnable)消费上一个任务完成后执行,无结果传递上一个任务异常时不执行
thenCompose(Function<? super T,? extends CompletionStage<U>>)组合链式异步调用,顺序依赖可以避免嵌套CompletableFuture
thenCombine(CompletionStage<? extends U>, BiFunction<? super T,? super U,? extends V>)组合两个独立异步任务完成后合并结果两个任务都完成才执行
thenAcceptBoth(CompletionStage<? extends U>, BiConsumer<? super T,? super U>)组合两个独立任务完成后消费结果无返回值
runAfterBoth(CompletionStage<?> , Runnable)组合两个独立任务完成后执行,无结果传递无返回值
allOf(CompletableFuture<?>...)等待等待所有任务完成返回CompletableFuture<Void>,需自行获取每个结果
anyOf(CompletableFuture<?>...)等待任意一个任务完成即可返回CompletableFuture<Object>,需强转类型
exceptionally(Function<Throwable,? extends T>)异常处理捕获异常并返回默认值上游异常时触发
handle(BiFunction<? super T, Throwable, ? extends U>)异常处理对结果或异常处理无论异常与否都会执行
whenComplete(BiConsumer<? super T,? super Throwable>)异常处理对结果或异常进行观察,无返回值类似finally

核心方法:

创建:supplyAsync(), runAsync()
链式处理:thenApply(), thenAccept(), thenRun()
组合:thenCompose(), thenCombine(), allOf(), anyOf()
异常处理:exceptionally(), handle()

2. Demo

示例 1:异步任务执行

publicstaticvoiddemoRunAsync(){CompletableFuture.runAsync(()->{System.out.println("执行任务: "+Thread.currentThread().getName());}).join();}

示例 2:有返回值异步任务

publicstaticvoiddemoSupplyAsync(){intresult=CompletableFuture.supplyAsync(()->{return42;}).thenApply(x->x*2).join();System.out.println("结果: "+result);}

示例 3:组合两个任务

publicstaticvoiddemoThenCombine(){CompletableFuture<Integer>f1=CompletableFuture.supplyAsync(()->10);CompletableFuture<Integer>f2=CompletableFuture.supplyAsync(()->20);intsum=f1.thenCombine(f2,Integer::sum).join();System.out.println("组合结果: "+sum);}

示例 4:异常处理

publicstaticvoiddemoExceptionally(){CompletableFuture<Integer>future=CompletableFuture.supplyAsync(()->{if(true)thrownewRuntimeException("出错了");return100;});intresult=future.exceptionally(ex->{System.out.println("捕获异常: "+ex.getMessage());return-1;}).join();System.out.println("最终结果: "+result);}

示例 5:等待多个任务完成

publicstaticvoiddemoAllOf(){CompletableFuture<Integer>f1=CompletableFuture.supplyAsync(()->10);CompletableFuture<Integer>f2=CompletableFuture.supplyAsync(()->20);CompletableFuture<Integer>f3=CompletableFuture.supplyAsync(()->30);CompletableFuture<Void>all=CompletableFuture.allOf(f1,f2,f3);all.join();// 等待所有任务完成intsum=f1.join()+f2.join()+f3.join();System.out.println("总和: "+sum);}

大的一个Demo:

importjava.util.concurrent.*;publicclassCompletableFutureDemo{publicstaticvoidmain(String[]args)throwsException{ExecutorServiceexecutor=Executors.newFixedThreadPool(3);// 异步任务1CompletableFuture<Integer>future1=CompletableFuture.supplyAsync(()->{System.out.println("任务1执行线程: "+Thread.currentThread().getName());return10;},executor);// 异步任务2CompletableFuture<Integer>future2=CompletableFuture.supplyAsync(()->{System.out.println("任务2执行线程: "+Thread.currentThread().getName());return20;},executor);// 组合任务:任务1和任务2完成后求和CompletableFuture<Integer>resultFuture=future1.thenCombine(future2,(a,b)->a+b);// 处理结果和异常resultFuture.thenAccept(sum->System.out.println("结果: "+sum)).exceptionally(ex->{System.out.println("异常:"+ex.getMessage());returnnull;});// 等待所有任务完成resultFuture.join();executor.shutdown();}}

截图如下:

3. 实战

之所以有这个知识点,是因为我原先的异步写错了,导致有这个总结的思路

上述意思如下:

线程A: 算法1算法2算法3

实际应该如下:

线程A:算法1线程B:算法2线程C:算法3

实际如下:

AI 算法AFuture<TaskResult>AI 算法BFuture<TaskResult>AI 算法CFuture<TaskResult>↓ allOf 等待 ↓ 汇总结果给前端

大致的Demo如下:

publicclassAiRecognition{publicstaticStringTOKEN="xxx";// === 线程池(生产环境建议交给 Spring 管理)===privatestaticfinalExecutorServiceEXECUTOR=Executors.newFixedThreadPool(3);/** * 三个 AI 算法并发识别 */publicstaticCompletableFuture<AiCheckResult>aiCheckAll(StringimgUrlF,StringimgUrlL,StringimgUrlI){CompletableFuture<TaskResult>containerFuture=CompletableFuture.supplyAsync(()->safeContainerCheck(imgUrlF),EXECUTOR);CompletableFuture<TaskResult>doorFuture=CompletableFuture.supplyAsync(()->safeDoorCheck(imgUrlL),EXECUTOR);CompletableFuture<TaskResult>innerFuture=CompletableFuture.supplyAsync(()->safeInnerCheck(imgUrlI),EXECUTOR);returnCompletableFuture.allOf(containerFuture,doorFuture,innerFuture).thenApply(v->{List<TaskResult>list=Arrays.asList(containerFuture.join(),doorFuture.join(),innerFuture.join());AiCheckResultresult=newAiCheckResult();result.setDetails(list);result.setSuccess(list.stream().allMatch(TaskResult::isSuccess));returnresult;});}// === 以下是单个算法的安全封装 ===privatestaticTaskResultsafeContainerCheck(StringimgUrl){try{Stringdata=uploadImageAndRecognize(imgUrl,"http://xxxx");returnTaskResult.ok("containerNumber",data);}catch(Exceptione){returnTaskResult.fail("containerNumber",e.getMessage());}}privatestaticTaskResultsafeDoorCheck(StringimgUrl){try{Stringdata=uploadImageAndGetState(imgUrl,"http://xxxx");returnTaskResult.ok("doorState",data);}catch(Exceptione){returnTaskResult.fail("doorState",e.getMessage());}}privatestaticTaskResultsafeInnerCheck(StringimgUrl){try{Stringdata=uploadImageAndGetState(imgUrl,"http://xxxx");returnTaskResult.ok("innerState",data);}catch(Exceptione){returnTaskResult.fail("innerState",e.getMessage());}}}

1️⃣ 定义单个算法的返回结果

publicclassTaskResult{privateStringtaskName;privatebooleansuccess;privateStringdata;privateStringreason;publicstaticTaskResultok(StringtaskName,Stringdata){TaskResultr=newTaskResult();r.taskName=taskName;r.success=true;r.data=data;returnr;}publicstaticTaskResultfail(StringtaskName,Stringreason){TaskResultr=newTaskResult();r.taskName=taskName;r.success=false;r.reason=reason;returnr;}// getter / setter 省略}

2️⃣ 汇总返回给前端的结果

publicclassAiCheckResult{privatebooleansuccess;privateList<TaskResult>details;// getter / setter}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 5:51:38

JavaScript—— JavaScript 数字处理工具函数

数字处理工具函数 数字处理在各种业务场景中都很常见&#xff0c;尤其是涉及到金额计算、数据显示等方面。 // 添加千分位分隔符 function addThousandSeparator(num, decimals 2) {if (!num && num ! 0) return -;// 实现逻辑...return num.toString().replace(/\B(?…

作者头像 李华
网站建设 2026/4/16 7:03:12

JavaScript —— JavaScript 轮询机制和异步任务处理工具函数详解

在现代前端应用中,我们经常需要定期向服务器发送请求以获取最新数据,这种场景就需要用到轮询机制。本文介绍一种灵活、可靠的轮询工具函数实现方案。 技术难点 如何实现可控的轮询机制(开始、停止、重启) 如何处理轮询过程中的异常情况 如何限制轮询次数防止无限循环 如何…

作者头像 李华
网站建设 2026/4/15 22:11:30

英伟达与AI芯片竞争对手Groq达成授权协议并聘用其CEO

英伟达已与AI芯片竞争对手Groq达成非独家授权协议。作为交易的一部分&#xff0c;英伟达将聘用Groq创始人乔纳森罗斯、总裁桑尼马德拉以及其他员工。CNBC报道称&#xff0c;英伟达正以200亿美元收购Groq的资产&#xff1b;英伟达向TechCrunch表示&#xff0c;这并非对该公司的收…

作者头像 李华
网站建设 2026/4/16 7:10:04

Salesforce集成ChatGPT主要为防止客户数据泄露

Salesforce用户现在可以通过运行Agentforce与ChatGPT Enterprise或Edu版本直接从聊天机器人更新CRM数据。这一举措旨在遏制自制集成方案可能导致数据泄露到公司控制范围之外的风险。虽然这一合作被宣传为减少用户在OpenAI机器人和Salesforce之间切换时间的方式&#xff0c;但分…

作者头像 李华