Future和CompletableFuture的理解
Future:
一个Future
get():获取结果(可能会等待)
get(long timeout, TimeUnit unit):获取结果,但只等待指定的时间;
cancel(boolean mayInterruptIfRunning):取消当前任务;
isDone():判断任务是否已完成。
在调用get()时,如果异步任务已经完成,我们就直接获得结果。如果异步任务还没有完成,那么get()会阻塞,直到任务完成后才返回结果。
使用Future获得异步执行结果时,要么调用阻塞方法get(),要么轮询看isDone()是否为true,这两种方法都不是很好,因为主线程也会被迫等待。
CompletableFuture:
使用Future获得异步执行结果时,要么调用阻塞方法get(),要么轮询看isDone()是否为true,这两种方法都不是很好,因为主线程也会被迫等待。
从Java 8开始引入了CompletableFuture,它针对Future做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法
CompletableFuture
的优点是:
- 异步任务结束时,会自动回调某个对象的方法;
- 异步任务出错时,会自动回调某个对象的方法;
- 主线程设置好回调后,不再关心异步任务的执行。
CompletableFuture
可以指定异步处理流程:
thenAccept()
处理正常结果;exceptional()
处理异常结果;thenApplyAsync()
用于串行化另一个CompletableFuture
;anyOf()
和allOf()
用于并行化多个CompletableFuture
。
使用 CompletableFuture
的方法
-
直接使用
CompletableFuture
提交任务- 使用
CompletableFuture.runAsync()
或CompletableFuture.supplyAsync()
,这些方法会使用默认线程池来执行异步任务。 - 适合快速启动简单的异步操作,不需要额外的线程池管理。
- 使用
-
使用
CompletableFuture
并指定线程池- 通过
supplyAsync()
或runAsync()
的重载版本,接受Executor
参数,从而使用自定义线程池来执行任务。 - 适合需要对线程池进行配置和管理的场景,如调整线程数量、队列容量等。
java复制代码ExecutorService executor = Executors.newFixedThreadPool(10); CompletableFuture.supplyAsync(() -> { // 执行某些操作 return result; }, executor);
- 通过
-
通过线程池中的
submit()
方法获取CompletableFuture
- 使用
Executor
的submit()
方法(如executor.submit()
),结合CompletableFuture
来获取执行结果。 - 这通常会返回
Future
,但可以将结果转换为CompletableFuture
进行后续处理。
java复制代码Future<String> future = executor.submit(() -> { // 执行某些操作 return result; }); CompletableFuture<String> completableFuture = CompletableFuture.completedFuture(future.get());
- 使用
异常处理和结果回调
- 通过
thenApply()
、thenAccept()
和exceptionally()
等方法处理结果和异常。 CompletableFuture
提供了灵活的方式来组合多个异步操作,使得异步编程更容易。