CompletableFuture诞生于Java 8,是对Future的一种改进,由于使用Future会造成回调地狱,所以CompletableFuture应运而生。CompletableFuture是对Future的一种扩展,可以通过设置回调的方式处理计算结果,同时支持组合操作,一定程度解决了回调地狱的问题。
基本使用
supplyAsync
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void main(String[] args) { System.out.println(); System.out.println(Thread.currentThread().getName() + "冰红茶进入教室"); System.out.println(Thread.currentThread().getName() + "冰红茶坐在座位上");
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "老师正在走到教室"); System.out.println(Thread.currentThread().getName() + "老师到达教室");
return "准备上课!"; });
System.out.println(Thread.currentThread().getName() + "冰红茶正在自习"); System.out.println(String.format(Thread.currentThread().getName() + "%s 冰红茶开始听讲", cf.join())); }
|
suppluAsync的传入参数是一个函数式接口,返回一个泛型类型的值。在supplyAsync方法中,会创建一个新的线程来执行传入的函数式接口,返回一个CompletableFuture对象。
suppluAsync方法实现了函数重载,如下
1 2
| CompletableFuture<Object> supplyAsync(Supplier<Object>) CompletableFuture<Object> supplyAsync(Supplier<Object>, Executor)
|
第一个方法会使用ForkJoinPool.commonPool()作为线程池,第二个方法可以传入自定义的线程池。传入的任务就是从线程池中取出一个线程,然后进行执行的。
类似的有runAsync方法,runAsync方法没有返回值。
thenCompose
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void main(String[] args) { System.out.println(Thread.currentThread().getName() + "冰红茶进入教室"); System.out.println(Thread.currentThread().getName() + "冰红茶坐在座位上");
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "老师正在走到教室"); System.out.println(Thread.currentThread().getName() + "老师到达教室");
return "准备上课!"; }).thenCompose(msg -> { System.out.println("班长准备发言"); return CompletableFuture.supplyAsync(() -> msg + "班长:起立!"); });
System.out.println(Thread.currentThread().getName() + "冰红茶正在自习"); System.out.println(String.format(Thread.currentThread().getName() + "%s 冰红茶开始听讲", cf.join())); }
|
thenCompose方法是将两个CompletableFuture进行组合,第一个CompletableFuture的返回值会作为第二个CompletableFuture的入参。thenCompose方法的参数是一个Function函数式接口,返回一个CompletableFuture对象。
还有一个thenComposeAsync方法,和thenCompose差不多,就是异步执行,传入的任务会从线程池中取出一个线程进行执行。
thenCombine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void main(String[] args) { System.out.println(Thread.currentThread().getName() + "冰红茶进入教室"); System.out.println(Thread.currentThread().getName() + "冰红茶坐在座位上");
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "老师正在走到教室"); System.out.println(Thread.currentThread().getName() + "老师到达教室");
return "准备上课!"; }).thenCombine(CompletableFuture.supplyAsync(() -> { System.out.println("牢大坐在努力"); return "Man!! What can I say"; }), (msg1, msg2) -> msg1 + msg2);
System.out.println(Thread.currentThread().getName() + "冰红茶正在自习"); System.out.println(String.format(Thread.currentThread().getName() + "%s 冰红茶开始听讲", cf.join())); }
|
thenCombine方法是将两个CompletableFuture进行组合,第一个CompletableFuture的返回值和第二个CompletableFuture的返回值会作为入参。通过BiFunction函数式接口来处理前两个CompletableFuture的返回值作为入参,然后返回一个新的值。
类似的有thenAcceptBoth方法,不过thenAcceptBoth方法没有返回值。runAfterBoth方法也是类似的,不过runAfterBoth方法没有返回值,也没有入参。
thenApply
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void main(String[] args) { System.out.println(Thread.currentThread().getName() + "冰红茶进入教室"); System.out.println(Thread.currentThread().getName() + "冰红茶坐在座位上");
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "老师正在走到教室"); System.out.println(Thread.currentThread().getName() + "老师到达教室");
return "准备上课!"; }).thenApply(msg -> { System.out.println("班长发言"); return msg + "班长:全体起立!"; });
System.out.println(Thread.currentThread().getName() + "冰红茶正在自习"); System.out.println(String.format(Thread.currentThread().getName() + "%s 冰红茶开始听讲", cf.join())); }
|
thenApply方法是将CompletableFuture的返回值作为入参,然后返回一个新的值。thenApply方法的参数是一个Function函数式接口,返回一个新的值。用法和thenCompose差不多,只是thenCompose返回的是一个CompletableFuture对象。
类似的有thenAccept方法,thenAccept方法没有返回值。thenRun方法,没有入参和返回值。
applyToEither
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public static void main(String[] args) { System.out.println(Thread.currentThread().getName() + "冰红茶进入教室"); System.out.println(Thread.currentThread().getName() + "冰红茶坐在座位上");
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "老师正在走到教室"); System.out.println(Thread.currentThread().getName() + "老师到达教室");
return "准备上课!"; }).applyToEither(CompletableFuture.supplyAsync(() -> { System.out.println("牢大来咯");
return "Man!!!What can I say"; }), firstmsg -> firstmsg);
System.out.println(Thread.currentThread().getName() + "冰红茶正在自习"); System.out.println(String.format(Thread.currentThread().getName() + "%s 冰红茶开始听讲", cf.join())); }
|
applyToEither方法是将两个CompletableFuture进行组合,返回最快执行完的CompletableFuture的返回值。applyToEither方法的参数是一个CompletableFuture对象,返回一个新的值。
类似的有acceptEither方法,acceptEither方法没有返回值。runAfterEither方法也是类似的,没有入参和返回值。
exceptionally
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public static void main(String[] args) { System.out.println(Thread.currentThread().getName() + "冰红茶进入教室"); System.out.println(Thread.currentThread().getName() + "冰红茶坐在座位上");
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "老师正在走到教室"); System.out.println(Thread.currentThread().getName() + "老师到达教室"); return "准备上课!"; }).applyToEither(CompletableFuture.supplyAsync(() -> { System.out.println("牢大来咯"); return "Man!!!What can I say"; }), firstmsg -> { if ("准备上课!".equals(firstmsg)) { throw new RuntimeException("老师有事了"); } return firstmsg; }).exceptionally(e -> { System.out.println(e.getMessage()); return "这节课自习!"; });
System.out.println(Thread.currentThread().getName() + "冰红茶正在自习"); System.out.println(String.format(Thread.currentThread().getName() + "%s 冰红茶开始听讲", cf.join())); }
|
exceptionally方法是处理异常的,如果CompletableFuture执行过程中出现异常,会调用exceptionally方法,返回一个新的值。exceptionally方法的参数是一个Function函数式接口,返回一个新的值。
类似的有handle方法,handle方法也是处理异常的,不过handle方法的参数是一个BiFunction函数式接口(入参为正常执行的结果和异常的结果),返回一个新的值。whenComplete方法也是类似的,入参为正常执行的结果和异常的结果,不过whenComplete方法没有返回值。