CompletableFuture 常用方法小抄
关于 CompletableFuture, 引用 baeldung 中的一句话:
The best part of the CompletableFuture API is the ability to combine CompletableFuture instances in a chain of computation steps.
本文整理了 CompletableFuture 一些常用的方法,方便日后需要的时候查看。
回调
/**
* 总结:
* run:没参数传递,没返回值
* accept:有参数传递,没返回值
* apply:有参数传递,有返回值
*
* @author LBG - 2022/12/3
*/
public class CompletableFutureDemo {
public static void main(String[] args) throws Exception {
//runAsync();
//supplyAsync();
//thenRun();
//thenAccept();
//thenApply();
//exceptionally();
//whenComplete();
handle();
Thread.sleep(1000L);
}
/****************** 创建异步任务 ******************/
/**
* 创建一个无返回值的异步任务
*/
private static void runAsync() {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> System.out.println("runAsync demo"));
}
/**
* 创建一个有返回值的异步任务
*/
private static void supplyAsync() throws Exception {
CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> "has return value");
System.out.println(supplyAsync.get());
}
/****************** 异步任务完成后回调(没有参数传递,没有返回值) ******************/
/**
* 两个任务之间没有参数传递,且没有返回值
*/
private static void thenRun() {
CompletableFuture<Void> voidFuture =
CompletableFuture.supplyAsync(() -> "return value is thenRun")
.thenRun(() -> System.out.println("then run"));
}
/**
* 和 thenRun 的区别就是 thenRunAsync 可以传入自定义线程池
*/
private static void thenRunAsync() {
CompletableFuture<Void> voidFuture =
CompletableFuture.supplyAsync(() -> "return value is thenRunAsync")
.thenRunAsync(() -> System.out.println("thenRunAsync"));
}
/****************** 异步任务完成后回调(有参数传递,没有返回值) ******************/
/**
* 两个任务之间有参数传递,没有返回值
*/
private static void thenAccept() {
// thenAccept thenAcceptAsync 区别:后者可以传入线程池
CompletableFuture<Void> voidFuture =
CompletableFuture.supplyAsync(() -> "thenAccept value")
.thenAccept((value) -> System.out.println("previous value is " + value));
//ExecutorService pool = Executors.newFixedThreadPool(1);
//CompletableFuture<Void> voidFuture =
// CompletableFuture.supplyAsync(() -> "thenAccept value")
// .thenAcceptAsync((value) -> System.out.println("previous value is " + value), pool);
}
/****************** 异步任务完成后回调(有参数传递,有返回值) ******************/
/*
* 两个任务之间有参数传递,回调有返回值
*/
private static void thenApply() throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "one").thenApply((value) -> value + " two");
System.out.println(future.get());
//CompletableFuture<String> future = CompletableFuture
// .supplyAsync(() -> "one")
// .thenApplyAsync((value) -> value + " two", Executors.newFixedThreadPool(1));
//System.out.println(future.get());
}
/****************** 任务异常 ******************/
private static void exceptionally() throws Exception {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
int num = RandomUtils.nextInt(1, 10);
if (num < 6) {
throw new RuntimeException("exceptionally num " + num);
}
return num;
});
future.exceptionally((e) -> {
e.printStackTrace();
return null;
});
System.out.println(future.get());
}
/****************** 某个任务执行完成后,执行的回调方法,无返回值 ******************/
private static void whenComplete() throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "task value")
.whenComplete((val, e) -> System.out.println("task complete " + val));
System.out.println(future.get()); // 返回的是任务的返回值,不是 whenComplete
}
/****************** 某个任务执行完成后,执行的回调方法,返回值是任务的返回值 ******************/
/**
* 任务执行完的回调,有自己的返回值
*/
private static void handle() throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "handle value")
.handle((val, throwable) -> val + " handle");
System.out.println(future.get());
}
}
组合
public class CompletableFutureCombineDemo {
public static void main(String[] args) throws Exception {
// AND
//thenCombine();
//thenAcceptBoth();
// runAfterBoth();
// OR
//applyToEither();
//acceptEither();
//runAfterEither();
//allOf();
anyOf();
}
/****************** AND 两个任务都执行完后执行 ******************/
/**
* 两个任务的结果作为方法入参,且有返回值
*/
private static void thenCombine() throws Exception {
CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> "one");
CompletableFuture<String> twoFuture = CompletableFuture.supplyAsync(() -> "two");
CompletableFuture<String> threeFuture = twoFuture.thenCombine(oneFuture, (two, one) -> {
System.out.println(one);
System.out.println(two);
return "three";
});
System.out.println(threeFuture.get());
}
/**
* 两个任务的结果作为方法入参,无返回值
*/
private static void thenAcceptBoth() throws Exception {
CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> "one");
CompletableFuture<String> twoFuture = CompletableFuture.supplyAsync(() -> "two");
CompletableFuture<Void> voidFuture = twoFuture.thenAcceptBoth(oneFuture, (s, w) -> {
System.out.println(s);
System.out.println(w);
});
}
/**
* 无入参,无返回值
*/
private static void runAfterBoth() {
CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> "one");
CompletableFuture<String> twoFuture = CompletableFuture.supplyAsync(() -> "two");
twoFuture.runAfterBoth(oneFuture, () -> System.out.println("three"));
}
/****************** OR 两个任务有一个执行完执行 ******************/
private static String sleepAndReturn(String str) {
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(str);
return str;
}
private static String returnStr(String str) {
System.out.println(str);
return str;
}
/**
* 传参、有返回值
*/
private static void applyToEither() throws Exception {
CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> sleepAndReturn("one"));
CompletableFuture<String> twoFuture = CompletableFuture.supplyAsync(() -> returnStr("two"));
CompletableFuture<String> threeFuture = twoFuture.applyToEither(oneFuture, (val) -> {
System.out.println(val);
return "three";
});
System.out.println(threeFuture.get());
}
/**
* 传参、无返回值
*/
private static void acceptEither() {
CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> sleepAndReturn("one"));
CompletableFuture<String> twoFuture = CompletableFuture.supplyAsync(() -> returnStr("two"));
// void
CompletableFuture<Void> threeFuture = twoFuture.acceptEither(oneFuture, System.out::println);
}
/**
* 无传参,无返回值
*/
private static void runAfterEither() {
CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> sleepAndReturn("one"));
CompletableFuture<String> twoFuture = CompletableFuture.supplyAsync(() -> returnStr("two"));
// void
CompletableFuture<Void> threeFuture = twoFuture.runAfterEither(oneFuture, () -> System.out.println("three"));
}
/****************** AllOf ******************/
private static void allOf() throws Exception {
CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> sleepAndReturn("one"));
CompletableFuture<String> twoFuture = CompletableFuture.supplyAsync(() -> returnStr("two"));
CompletableFuture<String> threeFuture = CompletableFuture.supplyAsync(() -> returnStr("three"));
// void
CompletableFuture<Void> allFuture = CompletableFuture.allOf(oneFuture, twoFuture, threeFuture);
allFuture.get();
/*
* Notice that the return type of the CompletableFuture.allOf() is a CompletableFuture<Void>.
* The limitation of this method is that it does not return the combined results of all Futures.
* Instead, we have to get results from Futures manually.
* Fortunately, CompletableFuture.join() method and Java 8 Streams API makes it simple:
*/
List<String> resultList = Stream.of(oneFuture, twoFuture, threeFuture).map(CompletableFuture::join).collect(Collectors.toList());
System.out.println(JSONUtil.toJsonStr(resultList));
}
/****************** anyOf ******************/
private static void anyOf() throws Exception {
CompletableFuture<String> oneFuture = CompletableFuture.supplyAsync(() -> sleepAndReturn("one"));
CompletableFuture<String> twoFuture = CompletableFuture.supplyAsync(() -> returnStr("two"));
CompletableFuture<String> threeFuture = CompletableFuture.supplyAsync(() -> returnStr("three"));
// object
CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(oneFuture, twoFuture, threeFuture);
System.out.println("result is " + anyFuture.get());
}
/****************** thenCompose ******************/
private static void thenCompose() {
}
}