一、了解Future
CompletedFuture实现了Future接口,自Java 1.5以来有Future接口,Future类表示异步计算的未来结果,这个结果最终将在处理完成后出现在Future中。Future.isDone()方法用来检查计算是否完成,Future.get()获取计算完成返回结果,请注意,此方法会阻止执行,直到任务完成。Future.cancel(boolean)告诉执行程序停止操作并中断其底层线程。
public class FutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(5);
Future future = executorService.submit(() -> {
// 模拟异步计算
Thread.sleep(5000);
// 返回结果
return UUID.randomUUID().toString();
});
while (!future.isDone()){
System.out.println("wait done...");
Thread.sleep(1000);
}
System.out.println(future.get());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
publicclassFutureTest{
publicstaticvoidmain(String[]args)throwsExecutionException,InterruptedException{
ExecutorServiceexecutorService=Executors.newFixedThreadPool(5);
Futurefuture=executorService.submit(()->{
// 模拟异步计算
Thread.sleep(5000);
// 返回结果
returnUUID.randomUUID().toString();
});
while(!future.isDone()){
System.out.println("wait done...");
Thread.sleep(1000);
}
System.out.println(future.get());
}
}
执行结果
wait done...
wait done...
wait done...
wait done...
wait done...
wait done...
b3cc1f9f-6197-4049-bd46-5571aa10c159
1
2
3
4
5
6
7
waitdone...
waitdone...
waitdone...
waitdone...
waitdone...
waitdone...
b3cc1f9f-6197-4049-bd46-5571aa10c159
上面的例子虽然可以异步执行任务,但是却不能优雅的获取结果,只能是用阻塞或者轮询的方式来获取任务结果。轮询加阻塞,总是给人一种怪怪的感觉。
所以,在Java 8中, 新增加了一个包含50个方法左右的类: CompletableFuture,提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法。
二、 CompletableFuture 类介绍
2.1 创建 CompletableFuture
2.1.1 可以使用简单的构造方法
new CompletableFuture();
1
newCompletableFuture();
2.1.2 使用静态方法
public static CompletableFuture runAsync(Runnable runnable)
public static CompletableFuture runAsync(Runnable runnable, Executor executor)
public static CompletableFuture supplyAsync(Supplier supplier)
public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)
1
2
3
4
publicstaticCompletableFuturerunAsync(Runnablerunnable)
publicstaticCompletableFuturerunAsync(Runnablerunnable,Executorexecutor)
publicstaticCompletableFuturesupplyAsync(Suppliersupplier)
publicstaticCompletableFuturesupplyAsync(Suppliersupplier,Executorexecutor)
2.2 获取计算结果
保留了原有的get()和get(long timeout, TimeUnit unit)方法,另外还新增了
public T getNow(T valueIfAbsent)
public T join()
1
2
publicTgetNow(TvalueIfAbsent)
publicTjoin()
get(long timeout, TimeUnit unit)表示只在限定时间内等待获取结果,超时就抛出异常。
getNow(T valueIfAbsent)表示如果已经计算完就立马返回结果或者抛出异常,否则就返回预设的valueIfAbsent。
join()也是用来获取返回的结果,如果有异常就抛出一个unchecked异常( CompletionException ),它和get()抛出的异常不一样,可以分别运行一下下面两行代码
CompletableFuture.supplyAsync(() -> "".substring(10)).get();
CompletableFuture.supplyAsync(() -> "".substring(10)).join();
1
2
CompletableFuture.supplyAsync(()->"".substring(10)).get();
CompletableFuture.supplyAsync(()->"".substring(10)).join();
第一张图是get()的结果,第二张图是join()的结果
2.3 计算完成后的动作处理
当CompletableFuture的计算结果完成,或者抛出异常的时候,我们可以执行特定的Action。主要是下面的方法:
public CompletableFuture whenComplete(BiConsumer super T,? super Throwable> action)
public CompletableFuture whenCompleteAsync(BiConsumer super T,? super Throwable> action)
public CompletableFuture whenCompleteAsync(BiConsumer super T,? super Throwable> action, Executor executor)
public CompletableFuture exceptionally(Function fn)
1
2
3
4
publicCompletableFuturewhenComplete(BiConsumer<?superT ,?superThrowable>action)
publicCompletableFuturewhenCompleteAsync(BiConsumer<?superT ,?superThrowable>action)
publicCompletableFuturewhenCompleteAsync(BiConsumer<?superT ,?superThrowable>action,Executorexecutor)
publicCompletableFutureexceptionally(Functionfn)
带Async的方法,说明是以新的线程池运行,而具体是不是新的线程池,那就要看这里指定的线程池是不是和创建CompletableFuture时指定的一样,另外,如果是同一个线程池,也有可能被同一个线程选中。
一个简单的示例
final String[] result = {""};
CompletableFuture.supplyAsync(() -> UUID.randomUUID().toString())
.whenComplete((s, throwable) -> result[0] = s.replaceAll("-", ""))
.join();
System.out.println(result[0]);
1
2
3
4
5
finalString[]result={""};
CompletableFuture.supplyAsync(()->UUID.randomUUID().toString())
.whenComplete((s,throwable)->result[0]=s.replaceAll("-",""))
.join();
System.out.println(result[0]);
2.4 计算结果转换
有的时候我们需要直接将计算的结果A类转换为B类。CompletableFuture由于是回调风格,我们可以不必阻塞的告诉CompletableFuture当计算完成的时候请执行某个function。而且我们还可以将这些操作串联起来,或者将CompletableFuture组合起来。
看一下转换方法有哪些
public CompletableFuture thenApply(Function super T,? extends U> fn)
public CompletableFuture thenApplyAsync(Function super T,? extends U> fn)
public CompletableFuture thenApplyAsync(Function super T,? extends U> fn, Executor executor)
1
2
3
publicCompletableFuturethenApply(Function<?superT ,?extendsU>fn)
publicCompletableFuturethenApplyAsync(Function<?superT ,?extendsU>fn)
publicCompletableFuturethenApplyAsync(Function<?superT ,?extendsU>fn,Executorexecutor)
看下这个例子
List result = CompletableFuture.supplyAsync(() -> UUID.randomUUID().toString())
.thenApply(s -> Arrays.asList(s)).join();
result.stream().forEach(s -> System.out.println(s));
1
2
3
Listresult=CompletableFuture.supplyAsync(()->UUID.randomUUID().toString())
.thenApply(s->Arrays.asList(s)).join();
result.stream().forEach(s->System.out.println(s));
2.5 纯消费执行
上面的方法是当计算完成的时候,会生成新的计算结果(thenApply, handle),或者返回同样的计算结果whenComplete,CompletableFuture还提供了一种处理结果的方法,只对结果执行Action,而不返回新的计算值,因此计算值为Void:
public CompletableFuture thenAccept(Consumer super T> action)
public CompletableFuture thenAcceptAsync(Consumer super T> action)
public CompletableFuture thenAcceptAsync(Consumer super T> action, Executor executor)
public CompletableFuture thenAcceptBoth(CompletionStage extends U> other, BiConsumer super T,? super U> action)
public CompletableFuture thenAcceptBothAsync(CompletionStage extends U> other, BiConsumer super T,? super U> action)
public CompletableFuture thenAcceptBothAsync(CompletionStage extends U> other, BiConsumer super T,? super U> action, Executor executor)
public CompletableFuture runAfterBoth(CompletionStage> other, Runnable action)
1
2
3
4
5
6
7
publicCompletableFuturethenAccept(Consumer<?superT>action)
publicCompletableFuturethenAcceptAsync(Consumer<?superT>action)
publicCompletableFuturethenAcceptAsync(Consumer<?superT>action,Executorexecutor)
publicCompletableFuturethenAcceptBoth(CompletionStage<?extendsU>other,BiConsumer<?superT ,?superU>action)
publicCompletableFuturethenAcceptBothAsync(CompletionStage<?extendsU>other,BiConsumer<?superT ,?superU>action)
publicCompletableFuturethenAcceptBothAsync(CompletionStage<?extendsU>other,BiConsumer<?superT ,?superU>action,Executorexecutor)
publicCompletableFuturerunAfterBoth(CompletionStage>other,Runnableaction)
示例
CompletableFuture.supplyAsync(() -> UUID.randomUUID().toString())
.thenAccept(s -> {
// set s to db
}).join();
1
2
3
4
CompletableFuture.supplyAsync(()->UUID.randomUUID().toString())
.thenAccept(s->{
// set s to db
}).join();
浏览量:
205
0