Future特性
- 异步结果获取:可通过
get()
方法获取异步任务的执行结果,若任务未完成,get()
方法会阻塞当前线程,直到任务完成。
- 任务取消:提供
cancel(boolean mayInterruptIfRunning)
方法来取消任务。若mayInterruptIfRunning
为true
,正在执行的任务会被中断;若为false
,则仅在任务未开始时能取消。
- 判断任务状态:可通过
isDone()
判断任务是否完成,通过isCancelled()
判断任务是否被取消。
CompletableFuture特性
- 异步操作链:支持链式调用,能方便地将多个异步任务串联起来,例如
thenApply
、thenAccept
、thenRun
等方法,无需像Future
那样手动处理每个任务的结果获取与后续任务启动。
- 异步任务组合:可以将多个异步任务组合起来,如
allOf
方法等待所有任务完成,anyOf
方法只要有一个任务完成就返回。
- 回调处理:提供了丰富的回调方法,当任务完成时可以执行相应的回调,如
whenComplete
方法可在任务完成时得到任务结果或异常。
主要区别
- 编程模型:
Future
基于阻塞获取结果的模型,在获取结果时可能会阻塞线程。CompletableFuture
基于异步回调和链式调用,无需阻塞线程,更符合现代异步编程风格。
- 功能丰富度:
CompletableFuture
功能更丰富,支持异步任务的组合、链式调用以及多种回调处理方式,而Future
相对功能较为单一。
应用场景选择
- 简单异步任务且需要获取结果:如果只是简单的异步任务,并且需要在主线程等待任务执行完毕获取结果,
Future
就可以满足需求。例如,在一个工具类中执行一个简单的异步计算任务,主线程需要获取计算结果继续后续操作。
import java.util.concurrent.*;
public class FutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Integer> future = executorService.submit(() -> {
// 模拟异步任务
Thread.sleep(2000);
return 42;
});
System.out.println("等待任务执行完毕...");
Integer result = future.get();
System.out.println("任务结果: " + result);
executorService.shutdown();
}
}
- 复杂异步任务组合与链式操作:当涉及到多个异步任务的组合、链式调用以及需要灵活的回调处理时,应选择
CompletableFuture
。比如,在一个电商系统中,需要先查询商品库存,根据库存结果决定是否进行下单操作,并且在操作完成后记录日志。
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture.supplyAsync(() -> {
// 查询商品库存
System.out.println("查询商品库存...");
return 10;
})
.thenApplyAsync(stock -> {
if (stock > 0) {
System.out.println("库存充足,进行下单操作...");
return "订单已创建";
} else {
System.out.println("库存不足,无法下单");
return "下单失败";
}
})
.thenAcceptAsync(result -> System.out.println("操作结果: " + result))
.thenRunAsync(() -> System.out.println("记录操作日志..."));
// 主线程等待所有异步任务完成
Thread.sleep(3000);
}
}