在 java 的 completablefuture 中,手动完成一个任务最直接的方式是调用实例上的 complete() 方法。该方法会将结果设置为指定值并标记为已完成,如果任务尚未开始或正在运行,它会尝试中断当前执行线程;若任务已经完成或被取消,则返回 false 表示操作失败。对于需要处理异常的场景,可以使用 completeexceptionally() 方法来设置异常状态。以下是一个完整的示例程序,展示了如何创建、手动完成以及验证这些状态。

如何判断 CompletableFuture 是否已被手动完成
要判断一个 CompletableFuture 是否已经被手动完成,可以调用 isDone() 方法。如果 complete() 成功执行,isDone() 将返回 true。此外,可以通过 isCompletedExceptionally() 来区分是正常完成还是异常完成。在实际开发中,通常结合 complete() 的返回值来判断手动设置是否生效,因为如果任务已经由其他线程完成,手动设置会失败。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class ManualCompletionDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建一个空的 CompletableFuture
CompletableFuture<String> future = new CompletableFuture<>();
// 模拟异步任务
new Thread(() -> {
try {
Thread.sleep(1000); // 模拟耗时操作
System.out.println("Async task running...");
} catch (InterruptedException e) {
System.out.println("Task interrupted.");
}
}).start();
// 手动完成
boolean completed = future.complete("Manual Result");
System.out.println("Manual completion successful: " + completed);
System.out.println("Is done: " + future.isDone());
System.out.println("Result: " + future.get());
}
}
如何处理手动完成时的异常情况
当需要手动触发异常时,应使用 completeExceptionally(Throwable ex) 方法。这会将 CompletableFuture 的状态标记为异常完成,后续通过 get() 获取结果时会抛出 ExecutionException。与正常完成不同,异常完成不会中断正在运行的任务,而是等待其结束或将其取消(取决于具体实现和配置)。开发者可以通过捕获 CancellationException 或 ExecutionException 来处理这些情况。
立即学习“Java免费学习笔记(深入)”;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class ExceptionalCompletionDemo {
public static void main(String[] args) {
CompletableFuture<String> future = new CompletableFuture<>();
// 手动设置异常
future.completeExceptionally(new RuntimeException("Manual Exception"));
System.out.println("Is completed exceptionally: " + future.isCompletedExceptionally());
System.out.println("Is done: " + future.isDone());
try {
String result = future.get();
} catch (ExecutionException e) {
System.out.println("Caught exception: " + e.getCause().getMessage());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
基于 complete() 返回值的具体问题:已完成的 Future 再次调用 complete 会发生什么
如果一个 CompletableFuture 已经被其他线程或机制完成(例如通过 supplyAsync 或之前的 complete 调用),再次调用 complete() 将返回 false,且不会覆盖原有结果。这是为了确保并发安全,防止多个来源同时修改同一个 Future 的状态。开发者可以利用这一特性来实现“竞争”逻辑,即第一个成功完成的任务胜出,后续尝试均被忽略。


















