文章目录
上一篇文章介绍部分API CompletableFuture API用法介绍(一),这篇继续讲解CompletableFuture 其它API用法。
一、纯消费 API
单纯的去消费结果而不会返回新的值,因些计算结果为 Void;
1、thenAccep
- public CompletableFuture thenAccept(Consumer<? super T> action)
- public CompletableFuture thenAcceptAsync(Consumer<? super T> action)
- public CompletableFuture thenAcceptAsync(Consumer<? super T> action, Executor executor)】
public static void completableFuturThenAccep()throws Exception {
CompletableFuture<Void> future = CompletableFuture
.supplyAsync(() -> 10)
.thenAccept(System.out::println) //消费 上一级返回值 10
.thenAcceptAsync(System.out::println); //上一级没有返回值 输出null
System.out.println(future.get());//null
}
2、thenAcceptBoth
- public CompletableFuture thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action)
- public CompletableFuture thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action)
- public CompletableFuture thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action, Executor executor)
thenAccept 相比,参数类型多了一个 CompletionStage<? extends U> other,以上方法会接收上一个CompletionStage返回值,和当前的一个。
public static void complateFuturThenAcceptBoth() throws Exception {
CompletableFuture
.supplyAsync(() -> 10)
.thenAcceptBoth(CompletableFuture.supplyAsync(() -> 20), (a, b) -> {
System.out.println(a);
System.out.println(b);
}).get();
}
3、runAfterBoth
runAfterBoth 和以上方法不同,传一个 Runnable 类型的参数,不接收上一级的返回值
- public CompletableFuture runAfterBoth
- public CompletableFuture runAfterBothAsync
- public CompletableFuture runAfterBothAsync
public static void complateFuturRunAfterBoth() throws Exception {
System.out.println("开始");
CompletableFuture<Void> future = CompletableFuture
.supplyAsync(() -> {
System.out.println(10);
return 10;
})
.runAfterBoth(CompletableFuture.supplyAsync(() -> {
System.out.println(20);
return 20;
}), () -> System.out.println("开始运行run"));
System.out.println(future.get());
}
4、thenRun(Runnable action)
thenRun它的入参是一个Runnable的实例,表示当得到上一步的结果时的操作。
- public CompletionStage thenRun(Runnable action);
- public CompletionStage thenRunAsync(Runnable action);
- public CompletionStage thenRunAsync(Runnable action,Executor executor);
public static void complateFuturThenRun() throws Exception {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}).thenRun(() -> System.out.println("hello world"));
while (true){}
}
二、组合API
1、thenCompose
- public CompletableFuture thenCompose(Function<? super T,? extends CompletionStage> fn)
- public CompletableFuture thenComposeAsync(Function<? super T,? extends CompletionStage> fn)
- public CompletableFuture thenComposeAsync(Function<? super T,? extends CompletionStage> fn, Executor executor)
以上接收类型为 Function<? super T,? extends CompletionStage> fn ,fn 接收上一级返回的结果,并返回一个新的 CompletableFuture
public static void complateFuturThenCompose() throws Exception {
CompletableFuture<Integer> future = CompletableFuture
.supplyAsync(() -> 1)
.thenApply((a) -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return a + 10;
})
.thenCompose((s) -> {
System.out.println(s); //11
return CompletableFuture.supplyAsync(() -> s * 5);
});
System.out.println(future.get());//55
}
}
2、thenCombine
- public <U,V> CompletableFuture thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
- public <U,V> CompletableFuture thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
- public <U,V> CompletableFuture thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor)
两个CompletionStage是并行执行的,它们之间并没有先后依赖顺序,other并不会等待先前的CompletableFuture执行完毕后再执行。
thenCombine 和 supplyAsync 不一定哪个先哪个后,是并行执行的。
public static void complateFuturThenCombine() throws Exception {
Random random = new Random();
CompletableFuture<Integer> future = CompletableFuture
.supplyAsync(() -> {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("supplyAsync");
return 2;
}).thenApply((a) -> {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thenApply");
return a * 3;
})
.thenCombine(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thenCombineAsync");
return 10;
}), (a, b) -> {
System.out.println(a);
System.out.println(b);
return a + b;
});
System.out.println(future.get());
}
三、acceptEither / applyToEither
1、 acceptEither
- public CompletableFuture acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)
- public CompletableFuture acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action)
- public CompletableFuture acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor)
acceptEither方法是当任意一个 CompletionStage 完成的时候,action 这个消费者就会被执行。这个方法返回 CompletableFuture
public static void complateFuturAcceptEither() throws Exception {
Random random = new Random();
CompletableFuture
.supplyAsync(() -> {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
return "A";
})
.acceptEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
return "B";
}), System.out::println)
.get();
}
以上代码有时输出A,有时输出B,哪个Future先执行完就会根据它的结果计算。
3、 applyToEither
总会碰到有两种渠道完成同一个事情,所以就可以调用这个方法,找一个最快的结果进行处理。
- public CompletionStage applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn);
- public CompletionStage applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn);
- public CompletionStage applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor);
public static void complateFuturApplyToEitherr() throws Exception {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).applyToEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello world";
}), s -> s).join();
System.out.println(result);
}
acceptEither 没有返回值,applyToEither 有返回值
四、allOf / anyOf
1、allOf
- public static CompletableFuture allOf
这个方法的意思是把有方法都执行完才往下执行,没有返回值
public static void complateFuturAllOf() throws Exception {
Random random = new Random();
CompletableFuture.allOf(
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(1);
}),
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(2);
}))
.get();
}
2、anyOf
- public static CompletableFuture anyOf(CompletableFuture<?>… cfs)
任务一个方法执行完都往下执行,返回一个Object类型的值
public static void complateFuturAnyOf() throws Exception {
Random random = new Random();
Object o = CompletableFuture.anyOf(
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(random.nextInt(4000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(1);
}),
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(2);
}))
.get();
System.out.println(o);
}
以上就是CompletableFuture API的基本用法,根据业务灵活组合使用。对我们的编程会很有帮助。