能够异步去处理多任务
存在IO密集型的任务可以选择CompletableFuture,IO部分交由另外一个线程去执行。
Logback、Log4j2异步日志记录的实现原理就是新起了一个线程去执行IO操作,这部分可以以CompletableFuture.runAsync(()->{ioOperation();})的方式去调用。
如果是CPU密集型就不推荐使用了推荐使用并行流
CompletableFuture<String> future1 = new CompletableFuture<>();
通过CompletableFuture.completedFuture()方式
String message = "";
CompletableFuture<Object> future2 = CompletableFuture.completedFuture(message);
通过CompletableFuture.supplyAsync创建
CompletableFuture.supplyAsync(() -> {} )
CompletableFuture.supplyAsync(() -> {} , threadPool)
区别:后者可以传入自定义的线程池 前者使用默认的ForkJoinPool
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "" );
ExecutorService threadPool = Executors.newFixedThreadPool(4);
CompletableFuture<String> future4 = CompletableFuture.supplyAsync(() -> "" , threadPool);
通过CompletableFuture.runAsync创建
CompletableFuture.runAsync(() -> {} )
CompletableFuture.runAsync(() -> {} , threadPool)
区别:后者可以传入自定义的线程池 前者使用默认的ForkJoinPool
CompletableFuture<Void> future5 = CompletableFuture.runAsync(()->{});
ExecutorService threadPool = Executors.newFixedThreadPool(4);
CompletableFuture<Void> future6 = CompletableFuture.runAsync(()->{} , threadPool);
runAsync 和 supplyAsync 的区别
supplyAsync :有返回值
runAsync : 无返回值
会等待CompletableFuture处理完成才获取结果
future4.get()
如果在指定的时间内获取不到CompletableFuture的处理结果就抛出超时异常
TimeUnit.SECONDS : 为单位的意思 秒
future4.get(4, TimeUnit.SECONDS)
立刻获取处理结果 如果未处理完成就返回自定义的值
T valueIfAbsent : 和CompletableFuture 的返回值对应
future4.getNow("fail")
会等待CompletableFuture处理完成才获取结果
future4.join()
get 和 join 的区别
get : 需要用户手动抛出异常
join :用户不需要抛出异常
对计算结果的处理
以async结尾的方法将会在一个新的线程中执行组合操作
参数
BiConsumer : 定义对结果的处理
Executor : 自定义线程池
//方法一
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
//方法二
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
//方法三
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> 10/0);
CompletableFuture<Integer> cf2 = cf1.whenComplete((v, e) ->
System.out.println(String.format("值:%s, 异常:%s", v, e)));
System.out.println(cf2.join());
将前面计算结果的的CompletableFuture传递给thenApply,返回thenApply处理后的结果。
可以认为通过thenApply方法实现CompletableFuture
至CompletableFuture
的转换。
白话一点就是将CompletableFuture的计算结果作为thenApply方法的参数,返回thenApply方法处理后的结果
以async结尾的方法将会在一个新的线程中执行组合操作
参数
Function :对前一个CompletableFuture 计算结果的转化操作
Executor :自定义线程池
//方法一
public <U> CompletableFuture<U> thenApply(
Function<? super T,? extends U> fn) {
return uniApplyStage(null, fn);
}
//方法二
public <U> CompletableFuture<U> thenApplyAsync(
Function<? super T,? extends U> fn) {
return uniApplyStage(asyncPool, fn);
}
//方法三
public <U> CompletableFuture<U> thenApplyAsync(
Function<? super T,? extends U> fn, Executor executor) {
return uniApplyStage(screenExecutor(executor), fn);
}
CompletableFuture<Integer> result = CompletableFuture
.supplyAsync(其它API::randomInteger).thenApply((i) -> i * 8);
System.out.println(result.get());
说明:CompletableFuture先通过调用randomInteger方法获得值,然后把值作为thenApply中的参数进行*8。
和 thenApply 类似
区别就是 thenAccept 没有返回值
以async结尾的方法将会在一个新的线程中执行组合操作
参数
Consumer : 对前一个CompletableFuture计算结果的操作
Executor : 自定义线程池
//方法一
public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
return uniAcceptStage(null, action);
}
//方法二
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
return uniAcceptStage(asyncPool, action);
}
//方法三
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
Executor executor) {
return uniAcceptStage(screenExecutor(executor), action);
}
CompletableFuture.supplyAsync(其它API::getList)
.thenAccept(strList -> strList.forEach(System.out::println));
说明:CompletableFuture调用getList获取集合 再把该结果传递给thenAccept进行处理打印。
异步结果流水化
将两个异步操作进行流水操作
简单来说就是一个异步操作后把处理结果给另一个异步去操作
以async结尾的方法将会在一个新的线程中执行组合操作
参数
Function : 当前 CompletableFuture 计算结果的执行
Executor : 自定义线程池
//方法一
public <U> CompletableFuture<U> thenCompose(
Function<? super T, ? extends CompletionStage<U>> fn) {
return uniComposeStage(null, fn);
}
//方法二
public <U> CompletableFuture<U> thenComposeAsync(
Function<? super T, ? extends CompletionStage<U>> fn) {
return uniComposeStage(asyncPool, fn);
}
//方法三
public <U> CompletableFuture<U> thenComposeAsync(
Function<? super T, ? extends CompletionStage<U>> fn,
Executor executor) {
return uniComposeStage(screenExecutor(executor), fn);
}
CompletableFuture<Integer> result2 = CompletableFuture.supplyAsync(其它API::randomInteger)
.thenCompose(i -> CompletableFuture.supplyAsync(() -> i * 10));
System.out.println(result2.get());
说明:CompletableFuture通过randomInteger获取到值 把值传递给thenCompose方法 thenCompose再开另一个异步去处理这个值
组合结果,将两个无关的CompletableFuture组合起来,第二个Completable并不依赖第一个Completable的结果
创建方式
以async结尾的方法将会在一个新的线程中执行组合操作
参数
CompletionStage : 新的CompletableFuture的计算结果
BiFunction :对两个CompletableFuture的结果进行处理
Executor : 自定义线程池
//方法一
public <U,V> CompletableFuture<V> thenCombine(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn) {
return biApplyStage(null, other, fn);
}
//方法二
public <U,V> CompletableFuture<V> thenCombineAsync(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn) {
return biApplyStage(asyncPool, other, fn);
}
//方法三
public <U,V> CompletableFuture<V> thenCombineAsync(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn, Executor executor) {
return biApplyStage(screenExecutor(executor), other, fn);
}
CompletableFuture<Integer> result3 = CompletableFuture.supplyAsync(其它API::randomInteger)
.thenCombine(CompletableFuture.supplyAsync(其它API::randomInteger),
(i, j) -> i * j);
System.out.println(result3.get());
说明:CompletableFuture调用randomInteger获取值 在调用thenCombine,thenCombine开另一个CompletableFuture去获取另外一个值,这两个值同时交由thenCombine处理。
组合多个CompletableFuture
意思就是allOf会等待所有的CompletableFuture都执行了才会继续走下面的流程
所有的CompletableFuture都执行完后执行计算
allOf方法没有返回值,适合没有返回值并且需要前面所有任务执行完毕才能执行后续任务的应用场景
//allOf
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {
return andTree(cfs, 0, cfs.length - 1);
}
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("hello");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("world");
return "world";
});
CompletableFuture<Void> result4 = CompletableFuture.allOf(future1, future2);
System.out.println(result4.get() + " success");
说明:allOf会等待future1 和 future2都执行完成才会走下面的输出操作
组合多个CompletableFuture
意思就是anyOf会等待只要有一个CompletableFuture执行了就会继续走下面的流程
任意一个CompletableFuture执行完后就会执行计算
该方法比较适合只要有一个返回值就可以继续执行其他任务的应用场景
//anyOf
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
return orTree(cfs, 0, cfs.length - 1);
}
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
randomSleep();
System.out.println("112121");
return "11111111";});
CompletableFuture<String> future6 = CompletableFuture.supplyAsync(() -> {
randomSleep();
System.out.println("127777");
return "222222222";});
CompletableFuture<Object> result8 = CompletableFuture.anyOf(future3, future6);
System.out.println(result8.get());
说明: 两个线程都会将结果打印出来,但是get方法只会返回最先完成任务的结果 。
很多方法都提供了异步实现【带async后缀】,但是需小心谨慎使用这些异步方法
因为异步意味着存在上下文切换,可能性能不一定比同步好。
如果需要使用异步的方法,先做测试,用测试数据说话!!!