做网站要什么软件,泉州seo优化,公司发展规划,网站建设经CompletableFuture 分别实现两个接口 Future与 CompletionStage。 Future 接口大家都比较熟悉#xff0c;这里主要讲讲 CompletionStage。
CompletableFuture 大部分方法来自CompletionStage 接口#xff0c;正是因为这个接口#xff0c;CompletableFuture才有如此强大功能…CompletableFuture 分别实现两个接口 Future与 CompletionStage。 Future 接口大家都比较熟悉这里主要讲讲 CompletionStage。
CompletableFuture 大部分方法来自CompletionStage 接口正是因为这个接口CompletableFuture才有如此强大功能。
想要理解 CompletionStage 接口我们需要先了解任务的时序关系的。我们可以将任务时序关系分为以下几种 串行执行关系 并行执行关系 AND 汇聚关系 OR 汇聚关系 1.串行执行关系
任务串行执行下一个任务必须等待上一个任务完成才可以继续执行。 CompletionStage 有四组接口可以描述串行这种关系分别为:
// 同步
CompletableFutureU thenApply(Function? super T, ? extends u fn)
CompletableFutureVoid thenAccept(Consumer? super T action)
CompletableFutureVoid thenRun(Runnable action)
// 这个比较特殊类似于Stream.flatmap
CompletableFutureU thenCompose(Function? super T, ? extends CompletionStageU fn)// 异步
CompletionStageU thenApplyAsync(Function? super T, ? extends u fn)
CompletionStageVoid thenAcceptAsync(Consumer? super T action)
CompletionStageVoid thenRunAsync(Runnable action)
// 这个比较特殊类似于Stream.flatmap
CompletionStageU thenComposeAsync(Function? super T, ? extends CompletionStageU fn)thenApply 方法需要传入核心参数为 FunctionT,R类型。这个类核心方法为 R apply(T t)
所以这个接口将会把上一个任务返回结果当做入参执行结束将会返回结果。
thenAccept 方法需要传入参数对象为 ConsumerT类型这个类核心方法为
void accept(T t)
返回值 void 可以看出这个方法不支持返回结果但是需要将上一个任务执行结果当做参数传入。
thenRun 方法需要传入参数对象为 Runnable 类型这个类大家应该都比较熟悉核心方法既不支持传入参数也不会返回执行结果。
thenCompose 方法作用与 thenApply 一样只不过 thenCompose 需要返回新的 CompletionStage。这么理解比较抽象可以集合代码一起理解。
CompletableFutureString cf CompletableFuture.supplyAsync(() - hello,楼下小哥);cf.thenApply(String::toLowerCase);
// 需要重新创建一个CompletionStage
cf.thenCompose(s - CompletableFuture.supplyAsync(s::toLowerCase));
方法中带有 Async 代表可以异步执行这个系列还有重载方法可以传入自定义的线程池上图未展示读者只可以自行查看 API。
最后我们通过代码展示 thenApply 使用方式
CompletableFutureString cf CompletableFuture.supplyAsync(() - hello,楼下小哥)// 1.thenApply(s - s 程序通事) // 2.thenApply(String::toUpperCase); // 3System.out.println(cf.join());
// 输出结果 HELLO,楼下小哥程序通事
这段代码比较简单首先我们开启一个异步任务接着串行执行后续两个任务。任务 2 需要等待任务1 执行完成任务 3 需要等待任务 2。
上面方法大家需要记住了 FunctionTRConsumerTRunnable 三者区别根据场景选择使用。2.AND 汇聚关系 如上所示只有任务 A 与任务 B 都完成之后任务 C 才会开始执行。
CompletionStage 有以下接口描述这种关系。
// 同步
CompletableFutureV thenCombine(CompletionStageU other, BiFunctionT,U,V fn)
CompletableFutureVoid thenAcceptBoth(CompletionStageU other, BiConsumerT,U action)
CompletableFutureVoid runAfterBoth(CompletionStageU other, Runnable action)// 异步
CompletableFutureV thenCombineAsync(CompletionStageU other, BiFunctionT,U,V fn)
CompletableFutureVoid thenAcceptBothAsync(CompletionStageU other, BiConsumerT,U action)
CompletableFutureVoid runAfterBothAsync(CompletionStageU other, Runnable action)// 多组任务
static CompletableFutureVoid allOf(CompletableFuture?... cfs)
thenCombine 方法核心参数 BiFunction 作用与 Function一样只不过 BiFunction 可以接受两个参数而 Function 只能接受一个参数。
thenAcceptBoth 方法核心参数BiConsumer 作用也与 Consumer一样不过其需要接受两个参数。
runAfterBoth 方法核心参数最简单上面已经介绍过不再介绍。
这三组方法只能完成两个任务 AND 汇聚关系如果需要完成多个任务汇聚关系需要使用 CompletableFuture#allOf不过这里需要注意这个方法是不支持返回任务结果。
AND 汇聚关系相关示例代码开头已经使用过了这里再粘贴一下方便大家理解
// 任务1.订购航班
CompletableFutureString orderAirplane CompletableFuture.supplyAsync(() - {System.out.println(查询航班);sleep(3, TimeUnit.SECONDS);System.out.println(订购航班);return 航班信息;
});// 任务2.订购酒店
CompletableFutureString orderHotel CompletableFuture.supplyAsync(() - {System.out.println(查询酒店);sleep(5, TimeUnit.SECONDS);System.out.println(订购酒店);return 酒店信息;
});// 任务3.任务1和任务2都完成才能去订购租车服务
CompletableFutureString hireCar orderHotel.thenCombine(orderAirplane, (airplane, hotel) - {System.out.println(根据航班和酒店订购租车服务);sleep(5, TimeUnit.SECONDS);return 租车信息;
});// 等待任务3执行结果
System.out.println(hireCar.join());// 执行结果
查询航班
查询酒店
订购航班
订购酒店
根据航班和酒店订购租车服务
租车信息 3.OR 汇聚关系
有 AND 汇聚关系当然也存在 OR 汇聚关系。OR 汇聚关系代表只要多个任务中任一任务完成就可以接着接着执行下一任务。 CompletionStage 有以下接口描述这种关系
// 同步
CompletableFutureV applyToEither(CompletionStageU other, FunctionT,U fn)
CompletableFutureVoid acceptEither(CompletionStageU other, ConsumerT action)
CompletableFutureVoid runAfterEither(CompletionStageU other, Runnable action)// 异步
CompletableFutureV applyToEitherAsync(CompletionStageU other, FunctionT,U fn)
CompletableFutureVoid acceptEitherAsync(CompletionStageU other, ConsumerT action)
CompletableFutureVoid runAfterEitherAsync(CompletionStageU other, Runnable action)// 多组任务
static CompletableFutureVoid anyOf(CompletableFuture?... cfs)
前面三组接口方法传参与 AND 汇聚关系一致这里也不再详细解释了。
当然 OR 汇聚关系可以使用 CompletableFuture#anyOf 执行多个任务。
下面示例代码展示如何使用 applyToEither 完成 OR 关系。
CompletableFutureString cf CompletableFuture.supplyAsync(() - {sleep(5, TimeUnit.SECONDS);return hello,楼下小哥;
});// 1CompletableFutureString cf2 cf.supplyAsync(() - {sleep(3, TimeUnit.SECONDS);return hello程序通事;
});
// 执行 OR 关系
CompletableFutureString cf3 cf2.applyToEither(cf, s - s);// 输出结果由于 cf2 只休眠 3 秒优先执行完毕
System.out.println(cf2.join());
// 结果hello程序通事 4.异常处理
CompletableFuture 方法执行过程若产生异常当调用 getjoin获取任务结果才会抛出异常。
CompletableFutureInteger cf CompletableFuture.supplyAsync(() - (66/0)).thenApply(r - r*10);System.out.println(cf.join());// java.util.concurrent.CompletionException:java.lang.ArithmeticException: / by zero
上面代码我们显示使用 try..catch 处理上面的异常。不过这种方式不太优雅CompletionStage 提供几个方法可以优雅处理异常。
// 同步
CompletableFutureT exceptionally(FunctionThrowable, ? extends T fn)
CompletableFutureT whenComplete(BiConsumerT, ? super Throwable action)
CompletableFutureT handle(BiFunctionT, Throwable, ? extends U fn)// 异步
CompletableFutureT whenCompleteAsync(BiConsumerT, ? super Throwable action)
CompletableFutureT handleAsync(BiFunctionT, Throwable, ? extends U fn)
exceptionally 使用方式类似于 try..catch 中 catch代码块中异常处理。
whenComplete 与 handle 方法就类似于 try..catch..finanlly 中 finally 代码块。无论是否发生异常都将会执行的。这两个方法区别在于 handle 支持返回结果。
下面示例代码展示 handle 用法
CompletableFutureIntegerf0 CompletableFuture.supplyAsync(() - (7 / 0)).thenApply(r - r * 10).handle((integer, throwable) - {// 如果异常存在,打印异常并且返回默认值if (throwable ! null) {throwable.printStackTrace();return 0;} else {// 如果return integer;}});System.out.println(f0.join());
/***java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero* .....* * 0*/