编排两个非依赖关系的异步任务 - 两任务组合-两个任务任一完成执行
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,
Executor executor)
public CompletableFuture<Void> acceptEither(
CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(
CompletionStage<? extends T> other, Consumer<? super T> action)}
public CompletableFuture<Void> acceptEitherAsync(
CompletionStage<? extends T> other, Consumer<? super T> action,Executor executor)}
public <U> CompletableFuture<U> applyToEither(
CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(
CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(
CompletionStage<? extends T> other, Function<? super T, U> fn,Executor executor)
当两个任务中,任意一个future任务完成的时候,执行任务。
- applyToEither 两个任务有一个任务执行完成,获取它的返回值,处理任务并有新的返回值。
- acceptEither 两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
- runAfterEither 两个任务有一个执行完成,不需要获取future的结果,处理任务,也没有返回值。
RunAfterEitherAsync()
runAfterEither 两个任务有一个执行完成,不需要获取future的结果,处理任务,也没有返回值。
public class CompletableFutureRunAfterEitherAsync {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(5);
System.out.println("main start ...");
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("开启异步任务1...");
int i = 10 / 2;
return i;
}, executor);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("开启异步任务2...");
return "hello";
}, executor);
future1.runAfterEitherAsync(future2, () -> {
System.out.println("任务3 启动了....");
}, executor);
System.out.println("main end ...");
executor.shutdown();
}
}
执行结果:
main start ...
开启异步任务1...
main end ...
任务3 启动了....
开启异步任务2...
我们可以看到,任务1执行完成后,任务3不需要等待任务2执行完成,即可启动任务3。但是使用runAfterEitherAsync不能感知任务的返回值,自身也无返回值。
AcceptEither()
acceptEither 两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
public class CompletableFutureAcceptEither {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(5);
System.out.println("main start ...");
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("开启异步任务1...");
int i = 10 / 2;
return i;
}, executor);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("开启异步任务2...");
return 10;
}, executor);
future1.acceptEitherAsync(future2, (res) -> {
System.out.println("任务3 启动了...., 任务结果是:" + res);
}, executor);
System.out.println("main end ...");
executor.shutdown();
}
}
执行结果:
main start ...
开启异步任务1...
main end ...
任务3 启动了...., 任务结果是:5
开启异步任务2...
可以看到,可以获取任务1的执行结果,但不返回执行结果。
ApplyToEither()
applyToEither 两个任务有一个任务执行完成,获取它的返回值,处理任务并有新的返回值。
public class CompletableFutureApplyToEither {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(5);
System.out.println("main start ...");
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("开启异步任务1...");
int i = 10 / 2;
return i;
}, executor);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("开启异步任务2...");
return 10;
}, executor);
CompletableFuture<String> stringCompletableFuture = future1.applyToEitherAsync(future2, (res) -> {
System.out.println("任务3 启动了...., 上个任务结果是:" + res);
return "我是任务三的返回值, 上个任务的执行结果是:" + res;
}, executor);
System.out.println(stringCompletableFuture.get());
System.out.println("main end ...");
executor.shutdown();
}
}
执行结果:
main start ...
开启异步任务1...
任务3 启动了...., 上个任务结果是:5
我是任务三的返回值, 上个任务的执行结果是:5
main end ...
开启异步任务2...
编排多个非依赖关系的异步任务
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
- allOf:等待所有任务完成
- anyOf: 只要有一个任务完成
AllOf
allOf:等待所有任务完成
public class CompletableFutureAllOf {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(5);
System.out.println("main start ...");
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("查询商品图片...");
return "图片地址";
}, executor);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("查询商品属性...");
return "黑色 256G";
}, executor);
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
System.out.println("查询商品品牌...");
return "苹果手机";
}, executor);
CompletableFuture<Void> future = CompletableFuture.allOf(future1, future2, future3);
future.get();//等待索引结果完成
System.out.println("main end ...");
executor.shutdown();
}
}
执行结果:
main start ...
查询商品图片...
查询商品属性...
查询商品品牌...
main end ...
注:如果不使用future.get()阻塞,若其中一个任务执行时间较长,则可能会丢失任务信息。
AnyOf
public class CompletableFutureAnyOf {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(5);
System.out.println("main start ...");
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("查询商品图片...");
return "图片地址";
}, executor);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("查询商品属性...");
return "黑色 256G";
}, executor);
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
System.out.println("查询商品品牌...");
return "苹果手机";
}, executor);
CompletableFuture<Object> objectCompletableFuture = CompletableFuture.anyOf(future1, future2, future3);
System.out.println("第一个执行成功的数据:" + objectCompletableFuture.get());
System.out.println("main end ...");
executor.shutdown();
}
}
执行结果:
main start ...
查询商品图片...
查询商品属性...
第一个执行成功的数据:图片地址
main end ...
查询商品品牌...
实战案例
业务背景: 在电商项目的售后业务中,当客服接收到用户的售后申请时,需要进行一系列操作,包括查询订单信息、查询 ERP 中的商品信息、查询用户信息,以及创建售后工单。
public CompletableFuture<Void> processAfterSalesRequest(String orderId, String customerId) {
CompletableFuture<Order> orderFuture = CompletableFuture.supplyAsync(() -> getOrderInfo(orderId));
CompletableFuture<Inventory> inventoryFuture = CompletableFuture.supplyAsync(() -> getInventoryInfo(orderId));
CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> getUserInfo(customerId));
return CompletableFuture.allOf(orderFuture, inventoryFuture, userFuture)
.thenApplyAsync(ignored -> {
Order order = orderFuture.join();
Inventory inventory = inventoryFuture.join();
User user = userFuture.join();
// 创建售后工单
createAfterSalesTicket(order, inventory, user);
return null;
});
}
private Order getOrderInfo(String orderId) {
// 查询订单信息的逻辑
// ...
return order;
}
private Inventory getInventoryInfo(String orderId) {
// 查询ERP中商品信息的逻辑
// ...
return inventory;
}
private User getUserInfo(String customerId) {
// 查询用户信息的逻辑
// ...
return user;
}
private void createAfterSalesTicket(Order order, Inventory inventory, User user) {
// 创建售后工单的逻辑
// ...
}
在上述代码中,我们使用CompletableFuture.supplyAsync() 方法分别查询订单信息、ERP 中的商品信息和用户信息,然后使用CompletableFuture.allOf() 方法等待所有查询任务完成。完成后,我们可以通过join() 方法获取各个查询任务的结果,并将结果传递给createAfterSalesTicket() 方法来创建售后工单。