参考文章:
优雅处理并发:Java CompletableFuture最佳实践https://segmentfault.com/a/1190000044543793
CompletableFuture实践 https://blog.youkuaiyun.com/zsx_xiaoxin/article/details/123898171
选择 CompletableFuture 而非传统线程池方式,主要因为它提供了更强大、更灵活的异步编程能力。
在Java传统的Future模式里,咱们都知道,一旦开始了一个异步操作,就只能等它结束,无法知道执行情况,也不能手动完成或者取消。
而CompletableFuture呢,就像它的名字一样,是可以"完全控制"的Future。它提供了更多的控制,比如可以手动完成,可以处理异常,还可以把多个Future组合起来,进行更复杂的异步逻辑处理。
一、创建CompletableFuture
1. 使用supplyAsync
创建带有返回值的异步任务。
最常见的创建方式是使用CompletableFuture.supplyAsync()。这个方法需要一个Supplier函数接口,通常用于执行异步计算。来看看小黑怎么用:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 模拟耗时的计算
simulateTask("数据加载中");
return "结果";
});
这个例子中,simulateTask模拟了一个耗时操作,比如从数据库加载数据。
使用supplyAsync,咱们就能在另一个线程中执行这个任务,而主线程可以继续做其他事情。
2. 使用runAsync
创建没有返回值的异步任务。
如果咱们不关心异步任务的结果,只想执行一个异步操作,那就可以用runAsync。它接受一个Runnable函数接口,不返回任何结果:
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
simulateTask("正在执行一些处理");
});
在这个例子里,simulateTask只是执行了一些操作,比如记录日志或者发送通知,但不返回任何内容。
3. 手动完成complete
有时候,咱们可能需要手动完成一个Future。比如,基于某些条件判断,决定是否提前返回结果。这时候可以用complete方法:
CompletableFuture<String> manualFuture = new CompletableFuture<>();
// 在某些条件下手动完成Future
if (checkCondition()) {
manualFuture.complete("手动结果");
}
如果checkCondition返回true,那么这个Future就会被立即完成,否则它将保持未完成状态。
complete方法并不直接停止任何正在运行的任务。它只是设置结果并改变CompletableFuture的状态
获取任务结果的方法
// 如果完成则返回结果,否则就抛出具体的异常
public T get() throws InterruptedException, ExecutionException
// 最大时间等待返回结果,否则就抛出具体异常
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
// 完成时返回结果值,否则抛出unchecked异常。为了更好地符合通用函数形式的使用,如果完成此 CompletableFuture所涉及的计算引发异常,则此方法将引发unchecked异常并将底层异常作为其原因
public T join()
// 如果完成则返回结果值(或抛出任何遇到的异常),否则返回给定的 valueIfAbsent。
public T getNow(T valueIfAbsent)
// 如果任务没有完成,返回的值设置为给定值
public boolean complete(T value)
// 如果任务没有完成,就抛出给定异常
public boolean completeExceptionally(Throwable ex)
4. 组合使用thenCombine
CompletableFuture真正的魅力在于它的组合能力。假设小黑有两个独立的异步任务,咱们可以这样组合它们:
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
simulateTask("加载用户数据");
return "用户小黑";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
simulateTask("加载配置信息");
return "配置信息";
});
// 组合两个future,等待它们都完成
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (user, config) -> {
return "处理结果: " + user + "," + config;
})<

最低0.47元/天 解锁文章
5426






