其他异步编程方法
Java5中新增了Future接口,用来描述异步计算的结果。虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们的异步编程的初衷相违背,轮询的方式又会耗费无谓的 CPU 资源,而且也不能及时地得到计算结果。
CompletableFuture的优点支持事件回调(任务完成,任务异常等)由于它实现了Future接口,所以也可以用get()阻塞式的获取结果
支持串行执行、并行执行、合并异步结果、组合异步任务,即把上一个任务的输出作为下一个任务的输入
无需手工维护线程,语义清晰,代码优雅
使用方法
CompletableFuture的使用流程大致分为三步创建CompletableFuture对象
描述任务关系(串行,并行,汇聚)
处理异步计算结果
创建//比较特殊,入参就是返回值,返回值就是异步计算的结果
public static CompletableFuture completedFuture(U value)
//无返回值,使用默认线程池
public static CompletableFuture runAsync(Runnable runnable)
//无返回值,使用自定义线程池
public static CompletableFuture runAsync(Runnable runnable, Executor executor)
//有返回值,使用默认线程池
public static CompletableFuture supplyAsync(Supplier supplier)
//有返回值,使用自定义线程池
public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)
描述串行关系有Async的是异步方法//接收上一任务的输出并输出结果
CompletionStage thenApply(fn);
CompletionStage thenApplyAsync(fn);
//接收上一任务的输出,但不输出结果
CompletionStage thenAccept(consumer);
CompletionStage thenAcceptAsync(consumer);
//不接收输入,也不输出结果
CompletionStage thenRun(action);
CompletionStage thenRunAsync(action);
//和thenApply类似,类似map和flatmap的区别
CompletionStage thenCompose(fn);
CompletionStage thenComposeAsync(fn);
示例CompletableFuture.completedFuture("hello").thenApply(s -> {
System.out.println("任务1:"+Thread.currentThread().getId());
return s+" word";
}).thenApplyAsync(s->{
System.out.println("任务2:"+Thread.currentThread().getId());
return s+" !";
}).thenAccept(System.out::println);
System.out.println("主线程:"+Thread.currentThread().getId());
Thread.sleep(4000);
/*
输出结果
任务1:1
主线程:1
任务2:15
hello word !
*/
注意上面的代码,任务1是thenApply()同步方法,任务2是thenApplyAsync()异步方法。从输出结果可以看到,同步方法是在主线程执行的,而异步方法则丢到线程池执行。任务2虽然是异步方法,但由于是串行执行,它还是要等待任务1执行完毕才能执行。
描述AND汇聚关系//有Async的是异步方法
//接收上一任务的输出,并输出结果
CompletionStage thenCombine(other, fn);
CompletionStage thenCombineAsync(other, fn);
//接收上一任务的输出,但不输出结果
CompletionStage thenAcceptBoth(other, consumer);
CompletionStage thenAcceptBothAsync(other, consumer);
//不接收上一任务的输出,也不输出结果
CompletionStage runAfterBoth(other, action);
CompletionStage runAfterBothAsync(other, action);
示例
创建f1和f2两个异步任务,然后等待f1和f2都执行完毕,将结果相加后打印CompletableFuture f1=CompletableFuture.supplyAsync(()->"hello");
CompletableFuture f2=CompletableFuture.supplyAsync(()->"world");
f1.thenCombine(f2,(s, s2) -> s+" "+s2).thenAccept(System.out::println);
//输出hello world
描述OR汇聚关系//有Async的是异步方法
//接收上一任务的输出,并输出结果
CompletionStage applyToEither(other, fn);
CompletionStage applyToEitherAsync(other, fn);
//接收上一任务的输出,但不输出结果
CompletionStage acceptEither(other, consumer);
CompletionStage acceptEitherAsync(other, consumer);
//不接收上一任务的输出,也不输出结果
CompletionStage runAfterEither(other, action);
CompletionStage runAfterEitherAsync(other, action);
示例
创建两个异步任务,哪个任务先执行完就输出谁CompletableFuture f1 =
CompletableFuture.supplyAsync(()->{
int t = (int) (Math.random()*1000)+1000;
try {
Thread.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
return String.valueOf(t);
}).whenCompleteAsync((s, throwable) -> System.out.println(s));
CompletableFuture f2 =
CompletableFuture.supplyAsync(()->{
int t = (int) (Math.random()*1000)+1000;
try {
Thread.sleep(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
return String.valueOf(t);
}).whenCompleteAsync((s, throwable) -> System.out.println(s));
CompletableFuture f3 = f1.applyToEither(f2,s -> s);
System.out.println(f3.join());
Thread.sleep(2000);
事件回调//任务异常回调,有返回值,可以自己返回
CompletionStage exceptionally(fn);
//任务完成回调,有返回值,但这个返回值是异步任务的结果,我们不能返回
CompletionStage whenComplete(consumer);
CompletionStage whenCompleteAsync(consumer);
//任务完成回调,有返回值,可以自己返回
CompletionStage handle(fn);
CompletionStage handleAsync(fn);
示例CompletableFuture f0 =
CompletableFuture.supplyAsync(()->7/0).thenApply(r->r*10)
//放在exceptionally前面,可以获取到异步任务的结果,放在放在exceptionally后面,只能获取到exceptionally返回的结果
.whenComplete((integer, throwable) -> System.out.println(integer))
.exceptionally(t->{
t.printStackTrace();
//会覆盖异步任务的结果
return -1;
});
System.out.println(f0.join());
Thread.sleep(2000);
其他方法//接收多个CompletableFuture任务,等待全部任务执行完毕
public static CompletableFuture allOf(CompletableFuture>... cfs)
//接收多个CompletableFuture任务,等待任意一个任务执行完毕,并返回执行结果
public static CompletableFuture anyOf(CompletableFuture>... cfs)