1. 创建异步对象
CompletableFuture提供了4个静态的方法来创建一个异步操作
1.1 没有返回值
1)public static CompletableFuture<Void> runAsync(Runnable runnable)
2)public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
例如:
public class CompletableFutureTest {
// 创建一个10个线程的线程池 注意:一个系统应该只有有限的线程池,每个异步任务,都交给线程池,让其去执行
public static ExecutorService service = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main。。。");
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("线程" + Thread.currentThread().getId() + "运行结果:" + i);
}, service);
Void aVoid = future.get();
System.out.println(aVoid);
System.out.println("main。。。end");
}
}
执行结果:
通过执行结果,可以知道runXXX虽然是不带返回值的,其实我们也可以通过future.get()来获取到一个Void对象,其值为null,同时,get方法是阻塞的方法,所以main.end最后执行,因此,也可以使用get()方法来做线程控制。
1.2 带返回值
1)public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
2)public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)
注意:参数executor表示线程池,如果不传,那么使用默认的线程池
例如:
public class CompletableFutureTest {
// 创建一个10个线程的线程池 注意:一个系统应该只有有限的线程池,每个异步任务,都交给线程池,让其去执行
public static ExecutorService service = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main。。。");
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("线程" + Thread.currentThread().getId() + "运行结果:" + i);
return i;
}, service);
Integer i = future.get();
System.out.println("i = " + i);
System.out.println("main。。。end");
}
}
执行结果:
2. 方法完成时的感知whenComplete
CompletableFuture提供了类似JS中Promise的功能,可以让指定的任务执行完毕之后,回调某个函数,CompletableFuture也提供了四个回调函数
public CompletableFuture<T> whenComplete(
BiConsumer<? super T, ? super Throwable> action) {
return uniWhenCompleteStage(null, action);
}
public CompletableFuture<T> whenCompleteAsync(
BiConsumer<? super T, ? super Throwable> action) {
return uniWhenCompleteStage(asyncPool, action);
}
public CompletableFuture<T> whenCompleteAsync(
BiConsumer<? super T, ? super Throwable> action, Executor executor) {
return uniWhenCompleteStage(screenExecutor(executor), action);
}
public CompletableFuture<T> exceptionally(
Function<Throwable, ? extends T> fn) {
return uniExceptionallyStage(fn);
}
whenComplete和whenCompleteAsync可以处理正常和异常的计算结果,exceptionslly处理异常情况。
2.1 whenComplete与whenCompleteAsybc的区别
1)whenComplete:是执行当前任务的线程执行继续执行whenComplete的任务
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main。。。");
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("线程" + Thread.currentThread().getId() + "运行结果:" + i);
return i;
}, service).whenComplete((res,exception) -> {
System.out.printf("执行的结果是%d,异常信息是%s\r\n",res,exception);
});
System.out.println("main。。。end");
service.shutdown();
}
执行结果:
如果有异常
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main。。。");
CompletableFuture<Integer> future =
CompletableFuture.supplyAsync(() -> 10/0, service)
.whenComplete((res,exception) -> {
System.out.printf("执行的结果是%d,异常信息是%s\r\n",res,exception);
});
System.out.println("main。。。end");
service.shutdown();
}
运行结果:
2)whenCompleteAsync:是执行把whenCompleteAsync这个任务继续提交给线程池来进行执行
方法不以Async结果,意味着Action使用相同的线程执行,而Async可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
2.2 exceptionally异常处理
该方法可以捕获异常并给一个返回值。例如;
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main。。。");
CompletableFuture<Integer> future =
CompletableFuture.supplyAsync(() -> 10/0, service)
.whenComplete((res,exception) -> {
System.out.printf("执行的结果是%d,异常信息是%s\r\n",res,exception);
})
.exceptionally(e ->{
System.out.println(e);
return -1;
});
;
System.out.println("main。。。end " + future.get());
service.shutdown();
}
执行结果:
从中可以看出,exceptionally可以捕获异常对其进行处理,同时还可以给一个默认的返回值,而whenComplete方法虽然能得到异常信息,但是没法修改返回的数据,不能给默认的返回值。
3. 最终处理handler方法
handler可以处理执行成功与执行失败的返回
函数定义
public <U> CompletableFuture<U> handle(
BiFunction<? super T, Throwable, ? extends U> fn) {
return uniHandleStage(null, fn);
}
public <U> CompletableFuture<U> handleAsync(
BiFunction<? super T, Throwable, ? extends U> fn) {
return uniHandleStage(asyncPool, fn);
}
public <U> CompletableFuture<U> handleAsync(
BiFunction<? super T, Throwable, ? extends U> fn, Executor executor) {
return uniHandleStage(screenExecutor(executor), fn);
}
和complate一样,可对结果做最后的处理(可处理异常),可改变返回值。
例如:
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main。。。");
// R apply(T t, U u);
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 10 / 2, service).handleAsync((res, exception) -> {
if (null == exception) {
return res * 2;
} else {
return -1;
}
});
System.out.println("main。。。end "+future.get());
service.shutdown();
}
执行结果:
如果将2改成0,执行结果如图:
4. 线程串行化
4.1 thenApply
当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值
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);
}
例如:
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1启动了");
return 10 / 5;
}, service).thenApplyAsync(res -> {
System.out.println("任务1的结果:" + res);
return "任务1的结果*10 = " + res * 10;
}, service);
System.out.println(future.get());
}
执行结果:
4.2 thenAccept
消费处理结果,接收任务的处理结果,并消费处理,无返回结果
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);
}
例如;
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1启动了");
return 10 / 5;
}, service).thenAcceptAsync(res -> {
System.out.println("线程2启动了,线程1的执行结果:" + res);
}, service);
}
执行结果:
4.3 thenRun
只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行thenRun的后续操作
public CompletableFuture<Void> thenRun(Runnable action) {
return uniRunStage(null, action);
}
public CompletableFuture<Void> thenRunAsync(Runnable action) {
return uniRunStage(asyncPool, action);
}
public CompletableFuture<Void> thenRunAsync(Runnable action,
Executor executor) {
return uniRunStage(screenExecutor(executor), action);
}
例如:
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1启动了");
return 10 / 5;
}, service).thenRun(() -> {
System.out.println("任务1完成了");
System.out.println("任务2启动了");
}, service);
}
执行结果:
注意:因为thenRun没有返回值,因此返回的结果为Void。
5. 两任务组合——都要完成
5.1 thenCombine
组合两个future,获取两个future的返回结果,并返回当前任务的返回值
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);
}
例如:
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 任务1
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1启动了");
return 10 / 5;
});
// 任务2
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2启动了");
return "xxx";
});
CompletableFuture<String> future = future1.thenCombineAsync(future2, (res1, res2) -> {
return res1 + "_" + res2;
}, service);
System.out.println(future.get());
}
执行结果:
5.2 thenAcceptBoth
组合两个future,获取两个future的返回值,然后处理任务,没有返回值
public <U> CompletableFuture<Void> thenAcceptBoth(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action) {
return biAcceptStage(null, other, action);
}
public <U> CompletableFuture<Void> thenAcceptBothAsync(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action) {
return biAcceptStage(asyncPool, other, action);
}
public <U> CompletableFuture<Void> thenAcceptBothAsync(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action, Executor executor) {
return biAcceptStage(screenExecutor(executor), other, action);
}
例如:
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 任务1
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1启动了");
return 10 / 5;
});
// 任务2
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2启动了");
return "xxx";
});
future1.thenAcceptBothAsync(future2,(res1,res2)->{
System.out.println(res1+res2);
},service);
}
打印结果:
5.3 runAfterBoth
组合两个future,不需要获取future的结果,只需要两个future处理完任务后,处理该任务。
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,
Runnable action) {
return biRunStage(null, other, action);
}
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action) {
return biRunStage(asyncPool, other, action);
}
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action,
Executor executor) {
return biRunStage(screenExecutor(executor), other, action);
}
例如:
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 任务1
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1启动了");
return 10 / 5;
});
// 任务2
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2启动了");
return "xxx";
});
// 任务1和任务2都完成了执行任务三
future1.runAfterBothAsync(future1,()->{
System.out.println("任务3启动了");
},service);
}
执行结果:
6. 两任务组合-一个完成
当两个任务中,任意一个future任务完成的时候,执行任务
6.1 applyToEither
两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值
public <U> CompletableFuture<U> applyToEither(
CompletionStage<? extends T> other, Function<? super T, U> fn) {
return orApplyStage(null, other, fn);
}
public <U> CompletableFuture<U> applyToEitherAsync(
CompletionStage<? extends T> other, Function<? super T, U> fn) {
return orApplyStage(asyncPool, other, fn);
}
public <U> CompletableFuture<U> applyToEitherAsync(
CompletionStage<? extends T> other, Function<? super T, U> fn,
Executor executor) {
return orApplyStage(screenExecutor(executor), other, fn);
}
例如:
public static void main(String[] args) throws Exception {
// 任务1
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1启动了");
return 10 / 5;
});
// 任务2
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2启动了");
return 20;
});
CompletableFuture<String> future = future1.applyToEitherAsync(future2, res -> res + "_哈哈", service);
String res = future.get();
System.out.println("任务3的执行结果:" + res);
}
执行结果:
注意:res的值为任务1和任务2任意一个CompletableFuture的返回值,谁先执行完,res就代表谁的返回值。
6.2 acceptEither
两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值
public CompletableFuture<Void> acceptEither(
CompletionStage<? extends T> other, Consumer<? super T> action) {
return orAcceptStage(null, other, action);
}
public CompletableFuture<Void> acceptEitherAsync(
CompletionStage<? extends T> other, Consumer<? super T> action) {
return orAcceptStage(asyncPool, other, action);
}
public CompletableFuture<Void> acceptEitherAsync(
CompletionStage<? extends T> other, Consumer<? super T> action,
Executor executor) {
return orAcceptStage(screenExecutor(executor), other, action);
}
注意:acceptEither组合的两个CompletableFuture返回值需要是同类型的。
例如:
public static void main(String[] args) throws Exception {
// 任务1
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println("任务1启动了");
return 10 / 5;
});
// 任务3
CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2.1启动了");
return 20;
});
future1.acceptEitherAsync(future3,(res) -> {
Integer newRes = res.intValue() * 5;
System.out.println("任务3执行的结果:" + newRes);
},service);
}
执行结果:
6.3 runAfterEither
两个任务有一个执行完成,不需要获取future的结果,处理任务,也没返回值
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action) {
return orRunStage(null, other, action);
}
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action) {
return orRunStage(asyncPool, other, action);
}
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor) {
return orRunStage(screenExecutor(executor), other, action);
}
例如:
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 任务1
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1启动了");
return 10 / 5;
});
// 任务2
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println("任务2启动了");
return "xxx";
});
future1.runAfterEitherAsync(future2,()->{
System.out.println("任务3启动了");
},service);
}
执行结果:
从执行结果可以看出,任务1和任务2同时执行,任务2睡眠1s,任务1执行完成之后,立马执行任务3.
7. 多任务组合
7.1 allOf
等待所有任务完成
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {
return andTree(cfs, 0, cfs.length - 1);
}
例如:
public static void main(String[] args) throws Exception {
System.out.println("main start...");
// 任务1
CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询商品属性!");
return "attr";
},service);
// 任务2
CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询商品图片!");
return "hello.jpg";
},service);
// 任务3
CompletableFuture<String> futureInfo = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询商品信息!");
return "info";
},service);
CompletableFuture<Void> allOf = CompletableFuture.allOf(futureAttr, futureImg, futureInfo);
// allOf.join();
allOf.get(); // 等待所有结果完成
System.out.println("main end...");
}
执行结果:
从结果可以看出 allOf可以组合多个任务,等待所有的任务执行完成之后,在执行主线程
注意:allOf之后需要调用get或者join方法,阻塞等待。
7.2 anyOf
只要有一个任务完成
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
return orTree(cfs, 0, cfs.length - 1);
}
使用方式同allOf方法