1.异步编程
串行操作并行化,涉及到异步化
异步化,是并行方案得以实施的接触,利用多线程优化性能这个核心方案来实施的基础。
jdk1.8提供了CompletableFuture支持异步编程
2.CompletableFuture 核心优势
烧水泡茶,3个任务
任务1,洗水壶,烧开水
任务2,洗茶壶,洗茶杯,拿茶叶
任务3,泡茶
任务3需要等待任务1,和任务2都完成才可以执行
有一些没有见过的方法,
runAsync()
supplyAsync()
thenCombine()
特点:
1.无需手工维护线程,没有手工维护线程的工作,给任务分配线程不需要我们关注
2.语意清晰,f3 = f1.thenCombine(f2,() -> {})能够清晰表述“任务3等待任务1和任务2都完成后才开始”
3.代码简练,专注业务逻辑
//任务1:洗水壶->烧开水
CompletableFuture<Void> f1 =
CompletableFuture.runAsync(()->{
System.out.println("T1:洗水壶...");
sleep(1, TimeUnit.SECONDS);
System.out.println("T1:烧开水...");
sleep(15, TimeUnit.SECONDS);
});
//任务2:洗茶壶->洗茶杯->拿茶叶
CompletableFuture<String> f2 =
CompletableFuture.supplyAsync(()->{
System.out.println("T2:洗茶壶...");
sleep(1, TimeUnit.SECONDS);
System.out.println("T2:洗茶杯...");
sleep(2, TimeUnit.SECONDS);
System.out.println("T2:拿茶叶...");
sleep(1, TimeUnit.SECONDS);
return "龙井";
});
//任务3:任务1和任务2完成后执行:泡茶
CompletableFuture<String> f3 =
f1.thenCombine(f2, (__, tf)->{
System.out.println("T1:拿到茶叶:" + tf);
System.out.println("T1:泡茶...");
return "上茶:" + tf;
});
//等待任务3执行结果
System.out.println(f3.join());
void sleep(int t, TimeUnit u) {
try {
u.sleep(t);
}catch(InterruptedException e){}
}
// 一次执行结果:
T1:洗水壶...
T2:洗茶壶...
T1:烧开水...
T2:洗茶杯...
T2:拿茶叶...
T1:拿到茶叶:龙井
T1:泡茶...
上茶:龙井
3.CompletableFuture对象
创建
//使用默认线程池
static CompletableFuture<Void>
runAsync(Runnable runnable)
static <U> CompletableFuture<U>
supplyAsync(Supplier<U> supplier)
//可以指定线程池
static CompletableFuture<Void>
runAsync(Runnable runnable, Executor executor)
static <U> CompletableFuture<U>
supplyAsync(Supplier<U> supplier, Executor executor)
runAsync(Runnable runnable)
supplyAsync(Supplier supplier)
区别是什么?Runnable接口的run方法没有返回值,Supplier的get方法是有返回值的,其余额外的是带线程池传递
默认不传的话用的是默认ForkJoinPool线程池,线程数默认是cpu核数
建议根据不同业务类型创建不同的线程池,以免相互干扰
注意事项:
创建完CompletableFuture对象之后,自动异步执行runnable.run()方法或者supplier.get()方法
这也可以通过future来获取执行结果和判断线程是否执行结束。
4.CompletableFuture的高级功能
CompletableFuture类实现了CompletionStage接口,有40多个方法
CompletionStage接口
大概说明:
串行关系
并行关系
汇聚关系
异常处理
前面提到的f3 = f1.thenCombine(f2, () -> {})描述的就是汇聚关系,说白了就是AND聚合关系
f3是等f1,f2都执行完,才执行;当然还是or关系,只有其中1个执行完就可以执行
4.1 串行关系
thenApply,thenAccept,thenRun,thenCompose四个接口
CompletionStage<R> thenApply(fn);
CompletionStage<R> thenApplyAsync(fn);
CompletionStage<Void> thenAccept(consumer);
CompletionStage<Void> thenAcceptAsync(consumer);
CompletionStage<Void> thenRun(action);
CompletionStage<Void> thenRunAsync(action);
CompletionStage<R> thenCompose(fn);
CompletionStage<R> thenComposeAsync(fn);
4.2 and 汇聚关系
CompletionStage applyToEither(other, fn);
CompletionStage applyToEitherAsync(other, fn);
CompletionStage acceptEither(other, consumer);
CompletionStage acceptEitherAsync(other, consumer);
CompletionStage runAfterEither(other, action);
CompletionStage runAfterEitherAsync(other, action);
CompletionStage<R> thenCombine(other, fn);
CompletionStage<R> thenCombineAsync(other, fn);
CompletionStage<Void> thenAcceptBoth(other, consumer);
CompletionStage<Void> thenAcceptBothAsync(other, consumer);
CompletionStage<Void> runAfterBoth(other, action);
CompletionStage<Void> runAfterBothAsync(other, action);
4.3 or汇聚关系
CompletionStage applyToEither(other, fn);
CompletionStage applyToEitherAsync(other, fn);
CompletionStage acceptEither(other, consumer);
CompletionStage acceptEitherAsync(other, consumer);
CompletionStage runAfterEither(other, action);
CompletionStage runAfterEitherAsync(other, action);
4.4 异常处理
CompletableFuture<Integer>
f0 = CompletableFuture.
.supplyAsync(()->(7/0))
.thenApply(r->r*10);
System.out.println(f0.join());
正常是try-catch,函数式编程中,更简单,提供了链式处理异常
CompletionStage exceptionally(fn);
CompletionStage<R> whenComplete(consumer);
CompletionStage<R> whenCompleteAsync(consumer);
CompletionStage<R> handle(fn);
CompletionStage<R> handleAsync(fn);
异常范例
CompletableFuture f0 = CompletableFuture .supplyAsync(()->(7/0)) .thenApply(r->r*10) .exceptionally(e->0);System.out.println(f0.join());