CompletableFuture的基础用法介绍
CompletableFuture 基础用法介绍
第一章 创建过程
第01节 创建正常情况下已完成的Future
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 创建一个已完成的 CompletableFuture 的对象CompletableFuture<String> future = CompletableFuture.completedFuture("HelloWorld");// 获取到 CompletableFuture 的结果String content = future.get();// 输出结果System.out.println(content);}
}
运行结果
HelloWorld
第02节 创建异常情况下已完成的Future
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 创建一个已完成的 CompletableFuture 的对象CompletableFuture<String> future = CompletableFuture.failedFuture(new Throwable("我异常了"));// 获取到 CompletableFuture 的结果String content = future.get();// 输出结果System.out.println(content);}
}
运行结果
Exception in thread “main” java.util.concurrent.ExecutionException: java.lang.Throwable: 我异常了
at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396)
at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2073)
at com.completable.completable.Demo.main(Demo.java:13)
Caused by: java.lang.Throwable: 我异常了
at com.completable.completable.Demo.main(Demo.java:10)
第03节 异步执行任务 无返回
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 异步执行任务, 无返回。future 内部消化CompletableFuture<Void> future = CompletableFuture.runAsync(new Runnable() {@Overridepublic void run() {System.out.println("我是一个异步执行的任务, 在内部自己完成消化, 不会返回给外部使用, 本质就是一个异步线程");}});// 调用此方法, 完成上面的异步执行。如果不调用, 则不会显示结果future.get();}
}
运行结果
我是一个异步执行的任务, 在内部自己完成消化, 不会返回给外部使用, 本质就是一个异步线程
第04节 异步执行任务 有返回
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 异步执行任务, 有返回。将结果返回, 外部可以获取到值CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {@Overridepublic String get() {System.out.println("我是一个内部有返回的方法");return "我是返回值";}});// 调用此方法, 完成上面的异步执行。如果不调用, 则不会显示结果String content = future.get();System.out.println(content);}
}
运行结果
我是一个内部有返回的方法
我是返回值
第二章 获取结果
第01节 同步获取结果
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 异步执行任务CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {@Overridepublic String get() {System.out.println("我是一个内部有返回的方法");try {TimeUnit.SECONDS.sleep(5);return "正常情况";} catch (InterruptedException e) {return "异常值";}}});String content = future.get();System.out.println("正常 content = " + content);}
}
运行结果
我是一个内部有返回的方法
正常 content = 正常情况
第02节 超时获取结果
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 异步执行任务CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {@Overridepublic String get() {System.out.println("我是一个内部有返回的方法");try {TimeUnit.SECONDS.sleep(5);return "正常情况";} catch (InterruptedException e) {return "异常值";}}});String content = null;try {content = future.get(3, TimeUnit.SECONDS);System.out.println("正常 content = " + content);}catch (TimeoutException timeoutException){System.out.println("超时 content = " + content);}}
}// 说明:
// 1、在 future 内部定义了 5秒的延迟, 我们设置的超时时间是 3秒, 如果 3秒未获取到结果, 那么直接显示 超时
// 2、在 future 内部定义了 5秒的延迟, 如果 我们设置的超时时间是 5秒, 如果 5秒未获取到结果, 那么直接显示 超时 (两个时间相等时, 也是超时)
// 3、在 future 内部定义了 5秒的延迟, 如果 我们设置的超时时间是 6秒, 如果 5秒未获取到结果, 那么直接显示 正常 (大于延迟时间, 显示正常)
运行结果
我是一个内部有返回的方法
超时 content = null
第03节 获取默认结果
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 异步执行任务CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {@Overridepublic String get() {System.out.println("我是一个内部有返回的方法");return "正常情况";}});String content = future.getNow("默认值");System.out.println("content = " + content);}
}// 直接返回的是默认值, 不管里面的内容是否正常
运行结果
我是一个内部有返回的方法
content = 默认值
第04节 两类获取值操作
案例代码
public class Demo {public static void main(String[] args) {// 异步执行任务 有返回值 自定义线程CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {@Overridepublic String get() {try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {throw new RuntimeException(e);}return "正常值";}});// 采用Get 的方式获取数据值, 需要处理异常(可以解决超时的问题)try {String contentGet = future.get(2, TimeUnit.SECONDS);System.out.println("contentGet = " + contentGet);} catch (Exception exception) {System.out.println("出现异常的情况." + exception);}// 采用Join 的方式获取数据值, 无需处理异常(不能解决超时的问题)String contentJoin = future.join();System.out.println("contentJoin = " + contentJoin);}
}// 对比 Join 和 Get 两个方法
// 1、Get 方法需要处理异常, 可以定义超时时间, 在异常中关注 TimeOutException 可以处理超时的问题
// 2、Join 方法无需处理异常, 不可以定义超时时间, 可以用于 stream 流操作更方便。
运行结果
出现异常的情况.java.util.concurrent.TimeoutException
contentJoin = 正常值
第三章 自定义线程池操作
第01节 异步任务 无返回值 自定义线程池
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 异步执行任务 无返回值 自定义线程// 定义线程池ExecutorService executor = Executors.newFixedThreadPool(4);CompletableFuture<Void> future = CompletableFuture.runAsync(new Runnable() {@Overridepublic void run() {System.out.println("我是一个内部无返回的方法: " + Thread.currentThread().getName());}}, executor);future.get();// 关闭线程池executor.shutdown();}
}
运行结果
我是一个内部无返回的方法: pool-1-thread-1
第02节 异步任务 有返回值 自定义线程池
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 异步执行任务 有返回值 自定义线程// 定义线程池ExecutorService executor = Executors.newFixedThreadPool(4);CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {@Overridepublic String get() {System.out.println("我是一个内部有返回的方法: " + Thread.currentThread().getName());return "正常情况";}}, executor);String content = future.get();System.out.println("content = " + content);// 关闭线程池executor.shutdown();}
}
运行结果
我是一个内部有返回的方法: pool-1-thread-1
content = 正常情况
第四章 组合多个CompletableFuture
第01节 串联组合 thenCompose
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 顺序组合 thenCompose// 将 第01个CompletableFuture 的结果 str 与 第02个CompletableFuture 组合在一起CompletableFuture<String> future =CompletableFuture.supplyAsync(() -> {return "第01个CompletableFuture";}).thenCompose(str ->CompletableFuture.supplyAsync(() -> {return str.concat("第02个CompletableFuture");}));String content = future.get();System.out.println("结果: " + content);}
}// 类似于 物理电路图的 串联方式
运行结果
结果: 第01个CompletableFuture第02个CompletableFuture
效果图
第02节 并联组合 thenCombine
案例代码
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;public class Demo {public static void main(String[] args) throws Exception {// 并行组合 thenCombine// 将 第01个CompletableFuture 的结果 与 第02个CompletableFuture 收集存储在一起CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {return "第01个CompletableFuture";});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {return "第02个CompletableFuture";});CompletableFuture<List<String>> future = future1.thenCombine(future2, new BiFunction<String, String, List<String>>() {@Overridepublic List<String> apply(String s1, String s2) {List<String> list = new ArrayList<>();list.add(s1);list.add(s2);return list;}});List<String> content = future.get();System.out.println("结果: " + content);}
}// 类似于 物理电路图的 并联方式
运行结果
结果: [第01个CompletableFuture, 第02个CompletableFuture]
效果图
第03节 多任务全部完成 allOf
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 组合 allOf 等待所有的 CompletableFuture 完成之后, 给出通知CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("第01个CompletableFuture 完成");return "第01个CompletableFuture";});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("第02个CompletableFuture 完成");return "第02个CompletableFuture";});CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("第03个CompletableFuture 完成");return "第03个CompletableFuture";});// 组合所有的 futureCompletableFuture<Void> futureAll = CompletableFuture.allOf(future1, future2, future3);// 通知全部已经完成了CompletableFuture<Object> future = futureAll.thenApply(unused -> "所有的future都完成了");Object content = future.get();System.out.println("结果: " + content);}
}
运行结果
第01个CompletableFuture 完成
第02个CompletableFuture 完成
第03个CompletableFuture 完成
结果: 所有的future都完成了
效果图
第04节 多个任务任一完成 anyOf
代码
public class Demo {public static void main(String[] args) throws Exception {// 组合 anyOf 其中任何一个 future 完成就给通知CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("第01个CompletableFuture 完成");return "第01个CompletableFuture";});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("第02个CompletableFuture 完成");return "第02个CompletableFuture";});CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("第03个CompletableFuture 完成");return "第03个CompletableFuture";});// 并行完成多个 futureCompletableFuture<Object> futureAll = CompletableFuture.anyOf(future1, future2, future3);// 其中任何一个 future 完成就给通知CompletableFuture<Object> future = futureAll.thenApply(unused -> "有某个future完成了");Object content = future.get();System.out.println("结果: " + content);}
}
运行结果
第01个CompletableFuture 完成
结果: 有某个future完成了
效果图
第五章 链式调用
第01节 链式转换 thenApply
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 转换 thenApply 将前一个 CompletableFuture 的值 转换成为另一个值类型CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {System.out.println("第01个CompletableFuture 完成");return "ABCDEFGabcdefg";}).thenApply(new Function<String, String>() {@Overridepublic String apply(String element) {System.out.println("第02个CompletableFuture 完成: " + element);return element.toUpperCase();}}).thenApply(new Function<String, Integer>() {@Overridepublic Integer apply(String element) {System.out.println("第03个CompletableFuture 完成: " + element);return element.length();}});// 显示最终的结果int content = future.get();System.out.println("结果: " + content);}
}
运行结果
第01个CompletableFuture 完成
第02个CompletableFuture 完成: ABCDEFGabcdefg
第03个CompletableFuture 完成: ABCDEFGABCDEFG
结果: 14
第02节 终结链路 thenAccept
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 终结链路 thenAcceptCompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {System.out.println("第01个CompletableFuture 完成");return "ABCDEFGabcdefg";}).thenApply(new Function<String, String>() {@Overridepublic String apply(String element) {System.out.println("第02个CompletableFuture 完成: " + element);return element.toUpperCase();}}).thenApply(new Function<String, Integer>() {@Overridepublic Integer apply(String element) {System.out.println("第03个CompletableFuture 完成: " + element);return element.length();}});// 显示最终的结果, 终结链路。 thenAccept 将结果消费掉 Consumerfuture.thenAccept(new Consumer<Integer>() {@Overridepublic void accept(Integer count) {System.out.println("结果: " + count);}});}
}
运行结果
第01个CompletableFuture 完成
第02个CompletableFuture 完成: ABCDEFGabcdefg
第03个CompletableFuture 完成: ABCDEFGABCDEFG
结果: 14
第六章 异常处理
第01节 保留前面任务 exceptionally
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 异常处理, 保留前面任务 操作 exceptionallyCompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {System.out.println("第01个任务");return "result1";}).thenApply(s -> {int x = 3/0; // 这里出现异常System.out.println("第02个任务");return s + "-result2";}).thenApply(s -> {System.out.println("第03个任务");// 第三个return s + "-result3";}).exceptionally(throwable -> {System.out.println("异常: " + throwable);return "UnKnow";});String content = future.get();System.out.println("结果: " + content);}
}
运行结果
第01个任务
异常: java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
结果: UnKnow
第02节 保留后面任务 handle
案例代码
public class Demo {public static void main(String[] args) throws Exception {// 异常处理, 保留后面任务 操作 handleCompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {System.out.println("第01个任务");return "result1";}).handle(new BiFunction<String, Throwable, String>() {@Overridepublic String apply(String result, Throwable throwable) {if (throwable != null) {System.out.println("第01个任务, 出现异常: " + throwable);return "UnKnow";}return result;}}).thenApply(s -> {int x = 3 / 0; // 这里出现异常System.out.println("第02个任务");return s + "-result2";}).handle(new BiFunction<String, Throwable, String>() {@Overridepublic String apply(String result, Throwable throwable) {if (throwable != null) {System.out.println("第02个任务, 出现异常: " + throwable);return "UnKnow";}return result;}}).thenApply(s -> {System.out.println("第03个任务");// 第三个return s + "-result3";}).handle(new BiFunction<String, Throwable, String>() {@Overridepublic String apply(String result, Throwable throwable) {if (throwable != null) {System.out.println("第03个任务, 出现异常: " + throwable);return "UnKnow";}return result;}});String content = future.get();System.out.println("结果: " + content);}
}
运行结果
第01个任务
第02个任务, 出现异常: java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
第03个任务
结果: UnKnow-result3