找回密码
 会员注册
查看: 36|回复: 0

JavaCompletableFuture:你真的了解它吗?

[复制链接]

3

主题

0

回帖

10

积分

新手上路

积分
10
发表于 2024-9-3 16:46:52 | 显示全部楼层 |阅读模式
文章目录1什么是CompletableFuture?2如何正确使用CompletableFuture对象?3如何结合回调函数处理异步任务结果?4如何组合并处理多个CompletableFuture?1什么是CompletableFuture?CompletableFuture是Java8引入的一个强大的异步编程工具。允许以声明式的方式处理异步任务的结果,避免了传统回调和手动管理线程的复杂性。CompletableFuture可以组合和链式调用,高效地利用多核处理器的能力,并且减少了传统并发编程中常见的竞态条件和死锁等问题。在日常开发中,经常需要处理那些可能耗时的任务,比如网络请求、数据库查询或者复杂的计算。使用CompletableFuture,可以告诉程序如何在后台执行这些任务,然后在任务完成后执行特定的操作。可以想象一下,CompletableFuture就像是一条可以穿越时间的信使,你可以把一项任务托付给它,然后继续做其他事情。当任务完成时,它会及时将结果送回来,让你可以立即处理。这样,你就不必在等待任务完成的过程中浪费时间,而是可以更高效地利用自己的资源。2如何正确使用CompletableFuture对象?CompletableFuture可以以一种非阻塞的方式执行异步任务,并能够在任务完成后立即得到通知。通过链式调用的方式,可以很方便地组合多个异步操作,处理它们的结果或者异常。通过CompletableFuture.supplyAsync()方法创建一个CompletableFuture对象,并指定一个需要异步执行的任务://Supplier函数会在一个新的线程上异步执行CompletableFuturefuture=CompletableFuture.supplyAsync(()->{//模拟一个耗时操作,如从数据库中读取数据try{Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}return"异步任务完成";});12345678910通过在CompletableFuture上添加一些操作,比如处理任务的结果或者处理任务执行过程中可能发生的异常://thenAccept()方法接收一个Consumer函数future.thenAccept(result->{System.out.println("任务完成,结果为:"+result);}).exceptionally(ex->{System.out.println("任务出现异常:"+ex.getMessage());returnnull;});12345673如何结合回调函数处理异步任务结果?结合回调函数处理异步任务结果的过程可以比作在等待一份重要的快递时安排一个通知服务。这个通知服务就是回调函数,它会在快递送达时通知你,或者在处理完成后执行特定的操作。在Java的CompletableFuture中,这种模式可以通过supplyAsync()、thenApply()、thenAccept()和handle()方法来实现。创建一个异步任务时,使用CompletableFuture.supplyAsync()可以启动一个任务,这个任务在后台线程中执行,直到它完成。假设有一个任务需要从远程服务器获取数据://supplyAsync()方法接收一个Supplier函数,这个函数会在后台线程中运行,并返回一个结果//结果会被封装在CompletableFuture对象中,等待进一步处理CompletableFuturefuture=CompletableFuture.supplyAsync(()->{//模拟从远程服务器获取数据try{Thread.sleep(3000);}catch(InterruptedExceptione){e.printStackTrace();}return"数据已成功获取";});1234567891011使用thenApply()方法,可以在异步任务完成后,对结果进行转换。这个方法接收一个Function函数,这个函数会接收任务的结果,并返回一个新结果。比如,将获取的数据进行处理://thenApply()方法将原始数据转换为大写形式//处理后的结果会成为新的CompletableFuture对象的结果CompletableFutureprocessedFuture=future.thenApply(result->{//对结果进行处理returnresult.toUpperCase();});123456为了执行一个操作而不关心处理的结果,可以使用thenAccept()方法。这个方法接收一个Consumer函数,它处理任务完成时的结果,可以在异步任务完成时执行一些操作,比如日志记录或通知用户。例如,将结果打印到控制台://在任务完成后会调用传入的Consumer函数,并将结果传递给它future.thenAccept(result->{System.out.println("任务完成,结果是:"+result);});1234在任务执行过程中,可能会遇到异常。handle()方法可以用来处理这些异常,它接收一个BiFunction函数,这个函数接收结果和异常(如果有的话),并返回一个处理后的结果。例如://handle()方法检查是否有异常发生//如果有异常,它会处理异常并返回一个默认的结果//如果没有异常,它会处理正常的结果CompletableFuturehandledFuture=future.handle((result,ex)->{if(ex!=null){//处理异常System.out.println("任务发生错误:"+ex.getMessage());return"错误处理结果";}//处理正常结果returnresult.toLowerCase();});123456789101112对于这四种回调函数,可以使得异步任务的结果处理变得灵活而强大。通过结合使用不同的回调函数,可以对异步任务的结果进行多种操作,保证程序在处理复杂任务时仍然保持清晰和高效。4如何组合并处理多个CompletableFuture?组合和处理多个CompletableFuture可以让并发任务变得更加灵活和高效。设想有多个任务需要并行执行,然后将它们的结果结合起来进行进一步处理。在进行组合时,最基本的方法之一是将多个CompletableFuture的结果合并。比如,有两个任务需要并行完成,获取两个不同的数据源,然后将这两个结果结合起来。可以使用thenCombine()方法,它接收两个CompletableFuture和一个合并函数,两个CompletableFuture必须在相同的线程池中执行。假设有两个任务分别从不同的API获取数据:CompletableFuturefuture1=CompletableFuture.supplyAsync(()->{//模拟从第一个API获取数据return"数据1";});CompletableFuturefuture2=CompletableFuture.supplyAsync(()->{//模拟从第二个API获取数据return"数据2";});123456789为了将这两个结果结合起来,可以使用thenCombine()://thenCombine()方法接收两个CompletableFuture和一个函数,这个函数将两个任务的结果合并成一个结果//最终的结果是将两个字符串连接在一起CompletableFuturecombinedFuture=future1.thenCombine(future2,(result1,result2)->{//将两个结果结合成一个returnresult1+"和"+result2;});123456另一个有用的方法是allOf()方法。当有多个任务需要并行执行,并且在所有任务完成后执行某个操作时,allOf()非常有用。它接收一个CompletableFuture数组,并在所有这些CompletableFuture完成时触发。可以用来等待多个异步任务完成,然后执行某个操作:CompletableFutureallOfFuture=CompletableFuture.allOf(future1,future2);1要获取所有任务的结果,可以在allOf()的结果上添加一个回调函数://thenRun()方法会在所有任务完成后执行,它不需要处理结果,只是执行某个操作allOfFuture.thenRun(()->{//处理所有任务完成后的操作try{Stringresult1=future1.get();Stringresult2=future2.get();System.out.println("任务1的结果:"+result1);System.out.println("任务2的结果:"+result2);}catch(InterruptedException|ExecutionExceptione){e.printStackTrace();}});123456789101112如果有任务依赖于另一个任务的结果,可以使用thenCompose()方法。这种情况下,第二个任务会在第一个任务完成后开始执行。thenCompose()方法接收一个返回CompletableFuture的函数,然后将这两个CompletableFuture链接起来:CompletableFuturefuture3=future1.thenCompose(result1->{//使用第一个任务的结果来创建新的CompletableFuturereturnCompletableFuture.supplyAsync(()->result1+"处理完成");});1234对于这些方法来说,它们为处理多个异步任务提供了强大的工具,使得并发编程更加高效和灵活。通过合理使用这些方法,可以实现复杂的异步任务组合和处理逻辑,确保程序的高效执行。世界会向那些有目标和远见的人让路
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-28 05:09 , Processed in 0.437015 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表