Java8异步编程-CompletableFuture

异步编程的难点

如何优雅地实现异步编程一直都是一个难题,异步编程的通常做法就是采用callback的方法,但是这种方法通常会把代码嵌套在正常流程的代码中,而且当有多层嵌套的时候代码更加难以维护。
另外还有一点,异步编程的异常处理也是难以维护,特别是在Java中,异步编程通常由新的线程完成,而子线程的异常是无法在父线程捕获的,那么对于异步执行结果的获取就需要付出更大的代价,比如通过:轮询、事件驱动等来完成。

CompletableFuture

初识CompletableFuture
在Java8中引入了CompletableFuture类,同时实现了Future接口和CompletionStage接口,提供了一套用于异步编程的Api接口并且提供了异步处理
CompletableFuture提供了许多异步编程的操作,可以说是Java中的Promise了,下面通过CompletableFuture来实现上面提到的例子:

String userInfo = CompletableFuture.supplyAsync(() -> login())
    .thenApplyAsync(token -> userInfo(token))
    .get();
​
System.out.println(userInfo);

CompletableFuture API
CompletableFuture方法很多,功能也很丰富,这里不一一说明,主要可以分为这几类来使用:
1.把CompletableFuture当Future使用
CompletableFuture实现了Future接口,也就是Future能做的CompletableFuture也同样能使用,加上complete和completeExceptionally方法可以控制结果的结束:

CompletableFuture<String> f = new CompletableFuture<>();
​
Executors.newSingleThreadExecutor().submit(()->{
    f.complete("hello");
    //f.completeExceptionally(new RuntimeException("error"));
});
​
String result = f.get();
​
System.out.println(result);

CompletableFuture API
CompletableFuture方法很多,功能也很丰富,这里不一一说明,主要可以分为这几类来使用:
1.把CompletableFuture当Future使用
CompletableFuture实现了Future接口,也就是Future能做的CompletableFuture也同样能使用,加上complete和completeExceptionally方法可以控制结果的结束:

CompletableFuture<String> f = new CompletableFuture<>();
​
Executors.newSingleThreadExecutor().submit(()->{
    f.complete("hello");
    //f.completeExceptionally(new RuntimeException("error"));
});
​
String result = f.get();
​
System.out.println(result);
可以通过CompletableFuture来控制多个异步操作同时执行

CompletableFuture<String> f = new CompletableFuture<>();new Thread(() -> {
    try {
        System.out.println("thread1:" + f.get());
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}).start();new Thread(() -> {
    try {
        System.out.println("thread2:" + f.get());
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}).start();
​
f.complete("hello");

异步操作

public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)

使用如下:

public CompletableFuture<Void> thenRun(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action,Executor executor)
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn) 
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor) 
public CompletableFuture<Void> thenAccept(Consumer<? super T> action) 
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) 
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor)

连续异步操作

public CompletableFuture<Void> thenRun(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action,Executor executor)
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn) 
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor) 
public CompletableFuture<Void> thenAccept(Consumer<? super T> action) 
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) 
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor)

使用如下:

CompletableFuture<Void> f = CompletableFuture
                .supplyAsync(() -> "hello")
                .thenApplyAsync(res -> res + " world!")
                .thenAcceptAsync(System.out::println);
// wait for job done
f.get();

结果&异常处理

public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn) 
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn) 
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor) 
public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn)

使用如下:

// 异常处理
CompletableFuture<Object> f = CompletableFuture.supplyAsync(() -> "Hello")
        .thenApplyAsync(res -> res + "World")
        .thenApplyAsync(res -> {
            throw new RuntimeException("error");
        })
        .exceptionally(e -> {
            //handle exception here
            e.printStackTrace();
            return null;
        });
f.get();

// 执行结果处理

CompletableFuture<Object> f2 = CompletableFuture.supplyAsync(() -> "Hello")
        .thenApplyAsync(res -> res + "World")
        .thenApplyAsync(res -> {
            throw new RuntimeException("error");
        })
        .handleAsync((res, err) -> {
            if (err != null) {
                //handle exception here
                return null;
            } else {
                return res;
            }
        });
​
Object result = f2.get();
​
System.out.println(result);

并行执行异步操作并统一处理结果

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)

CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "hello");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "world");
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> "!");// 使用allOf方法
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);
all.get();
​
System.out.println(f1.get());
System.out.println(f2.get());
System.out.println(f3.get());


// 结合StreamAPI

List<String> result = Stream.of(f1, f2, f3)
        .map(CompletableFuture::join)
        .collect(Collectors.toList());
​
System.out.println(result);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不俏子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值