Java代码实现
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
class User {
private String name;
private int age;
private String address;
private String contact;
public User(String name, int age, String address, String contact) {
this.name = name;
this.age = age;
this.address = address;
this.contact = contact;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", contact='" + contact + '\'' +
'}';
}
}
public class CompletableFutureExample {
public static CompletableFuture<User> getUserInfo() {
// 模拟异步任务A
CompletableFuture<User> taskA = CompletableFuture.supplyAsync(() -> {
// 模拟获取用户对象
return new User("John", 30, null, null);
});
// 模拟异步任务B
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
// 模拟获取用户地址
return "123 Main St";
});
// 模拟异步任务C
CompletableFuture<String> taskC = CompletableFuture.supplyAsync(() -> {
// 模拟获取用户联系方式
return "123-456-7890";
});
return taskA.thenCombine(taskB, (user, address) -> {
user.address = address;
return user;
}).thenCombine(taskC, (user, contact) -> {
user.contact = contact;
return user;
}).exceptionally(ex -> {
System.out.println("任务执行出现异常: " + ex.getMessage());
return null;
});
}
public static void main(String[] args) {
try {
User user = getUserInfo().get();
if (user != null) {
System.out.println(user);
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
使用thenCombine
的优势
- 简洁的异步任务组合:
thenCombine
方法允许我们以一种链式调用的方式,简洁地将多个异步任务的结果进行合并。相比于传统的回调地狱或者手动管理多个线程和锁,这种方式代码结构更加清晰,易于理解和维护。
- 异步非阻塞:CompletableFuture本身基于异步和非阻塞的特性,
thenCombine
也继承了这一优点。它不会阻塞主线程,允许主线程在等待异步任务完成的同时继续执行其他操作,提高了程序的整体性能和响应性。
- 异常处理方便:通过
exceptionally
方法,可以方便地在链式调用中统一处理任务执行过程中可能出现的异常。这种集中式的异常处理机制使得代码更健壮,并且易于排查和定位问题。
注意事项
- 任务依赖关系:在使用
thenCombine
时,需要确保任务之间的依赖关系清晰。如果任务的执行顺序或者结果的合并逻辑出现错误,可能会导致程序逻辑错误。例如,如果任务B依赖于任务A的结果,而代码中没有正确处理这种依赖关系,可能会得到不正确的合并结果。
- 异常处理范围:虽然
exceptionally
方法提供了方便的异常处理机制,但需要注意异常处理的范围。它只会捕获当前CompletableFuture链中抛出的异常,如果异常发生在更外层或者其他独立的异步任务中,可能需要额外的处理机制。
- 内存管理:由于CompletableFuture在异步执行过程中可能会创建多个线程和对象,需要注意内存管理。特别是在高并发场景下,如果大量使用CompletableFuture而不及时释放资源,可能会导致内存泄漏和性能问题。
- 结果的一致性:在多个异步任务并行执行并合并结果时,要确保结果的一致性。例如,如果任务A和任务B都对同一个共享资源进行修改,需要考虑线程安全问题,以避免数据竞争和不一致的结果。