异步编程CompletableFuture
多线程优化性能,串行操作并行化
串行操作
// 以下2个都是耗时操作
doBizA();
doBizB();
修改变为并行化
new Thread(() -> doBizA()).start();
new Thread(() -> doBizB()).start();
异步化,是并行方案的基础,利用多线程优化性能。性能优化是大厂的核心需求
jdk1.8提供了CompletableFuture 来支持异步编程
CompletableFuture工具类还是很复杂的,需要做好心理准备
1.CompletableFuture实现烧水泡茶
任务3需要等待任务1和任务2都完成才能开始
范例
public static void tea(){
CompletableFuture<Void> f1 = CompletableFuture.runAsync(() -> {
System.out.println("T1:洗水壶...");
sleep(1);
System.out.println("T1:烧开水...");
sleep(15);
});
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
System.out.println("T2:洗茶壶...");
sleep(1);
System.out.println("T2:洗茶杯...");
sleep(2);
System.out.println("T2:拿茶叶...");
sleep(1);
return "龙井";
});
CompletableFuture<String> f3 = f1.thenCombine(f2,(__, tea) -> {
System.out.println("T1:拿到茶叶:" + tea);
System.out.println("T1:泡茶...");
return "tea:" + tea;
});
System.out.println(f3.join());
}
核心4个静态方法
runAsync(Runnable runnable) runnable接口的run方法没有返回值
supplyAsync(Supplier<U> supplier) Supplier接口的get方法有返回值
这2个方法,有重载方法,重载方法,支持传入自定义的线程池对象,默认不传使用的是jdk带的ForkJoinPool线程池,默认线程数是cpu核数的2倍
强烈建议,不同的业务类型创建不同的线程池,不要随便使用ForkJoinPool线程池,避免互相干扰
注意:
2个关注点
异步操作什么时候结束
如何获取异步操作的执行结果
都可以通过future接口get来解决
2.理解CompletionStage接口
1.串行关系
CompletableFuture f0 = CompletableFuture.supplyAsync( () -> "Hello World") //①
.thenApply(s -> s + " QQ") //②
.thenApply(String::toUpperCase);//③
System.out.println(f0.join());//输出结果HELLO WORLD QQ
2.AND汇聚关系
// 等f1,f2都执行完,f3开始执行
CompletableFuture<String> f3 = f1.thenCombine(f2,(__, tea) -> {
System.out.println("T1:拿到茶叶:" + tea);
System.out.println("T1:泡茶...");
return "tea:" + tea;
});
原创:做时间的朋友
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示