java 异步 future_Java8异步编程类CompletableFuture使用

一、了解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()的结果

4ec8919d8b3f7069d03be89acb6b87bb.png

83a695ff2ecc2c3bb290e571a6e2de78.png

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值