Java8-CompletableFuture简单api用法

2 篇文章 0 订阅

常见实现线程方法:

  1. 继承thread类
  2. 实现runnable接口

上述方式不能获得返回值,若想获得返回值其常见方式为实现callable接口,用Future描述一个异步计算的结果,但是获取一个结果时方法较少,要么通过轮询isDone,确认完成后,调用get()获取值,要么调用get()设置一个超时时间。但是这个get()方法会阻塞住调用线程,这种阻塞的方式显然和我们的异步编程的初衷相违背。

为了解决这个问题,Java8加入了CompletableFuture实现了CompletionStage和Future接口。

Java8之前的Future示例:

if (!CollectionUtils.isEmpty(servers)) {
        servers.stream().forEach(x->
                resultList.add(executorService.submit(() -> new X86CheckThread(x.getId(), x.getResourceId(), x.getServerName(), x.getStatus(), checkDto, sysUser).call())));
        }
        //创建power资源监测任务类置于线程池
        Page<PowerServerDTO> powerDTOPage = powerServerApplyService.listAllServerDTOS();
        List<PowerServerDTO> powers = powerDTOPage.getRecords();
if (!CollectionUtils.isEmpty(servers)) {
        powers.stream().forEach(x->
                resultList.add(executorService.submit(() -> new PowerCheckThread(x.getId(),x.getId(), x.getName(), x.getStatus(), checkDto, sysUser).call())));
        }


        resultList.stream().forEach(x-> {
            try {
                if (x.get().getFlag() == true) {
                    checkResponseDTOList.add(x.get());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }

        });

使用CompletableFuture改写示例:

if (!CollectionUtils.isEmpty(servers)) {
            servers.stream().forEach(x->{
                CheckResponseDTO checkResponse = CompletableFuture.supplyAsync(() -> new X86CheckThread(x.getId(), x.getResourceId(), x.getServerName(), x.getStatus(), checkDto, sysUser).call(), executorService).
                        whenComplete((s, e) -> logger.info("X86主机 "+x.getServerName()+"检测完成")).join();
                    checkResponseDTOList.add(checkResponse);
            });
        }
        //创建power资源监测任务类置于线程池
        Page<PowerServerDTO> powerDTOPage = powerServerApplyService.listAllServerDTOS();
        List<PowerServerDTO> powers = powerDTOPage.getRecords();
if (!CollectionUtils.isEmpty(powers)) {
            powers.stream().forEach(x->{
                CheckResponseDTO checkResponse = CompletableFuture.supplyAsync(() -> new PowerCheckThread(x.getId(), x.getResourceId(), x.getServerName(), x.getStatus(), checkDto, sysUser).call(), executorService).
                        whenComplete((s, e) -> logger.info("power主机 "+x.getName()+"检测完成")).join();
                checkResponseDTOList.add(checkResponse);
            });
        }
        List<CheckResponseDTO> collect = checkResponseDTOList.stream().filter(x -> x.getFlag() == true).collect(Collectors.toList());

CompletableFuture的api介绍:

/**
 * 转换api
 * public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
   public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn);
   public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor executor);
 * thenApply它的入参是上一个阶段计算后的结果,返回值是经过转化后结果。
 */
@Test
public void testThenApply() {
    String join = CompletableFuture.supplyAsync(() -> "hello").thenApply(s -> s + "world").join();
    System.out.println(join);
}
/**
 * 消耗api
 * public CompletionStage<Void> thenAccept(Consumer<? super T> action);
   public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
   public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor);
 thenAccept是针对结果进行消耗,因为他的入参是Consumer,有入参无返回值。
 */
@Test
public void testThenAccept() {
    CompletableFuture.supplyAsync(() -> "hello ").thenAccept(s -> System.out.println(s + "world"));
}
/**
 * public CompletionStage<Void> thenRun(Runnable action);
   public CompletionStage<Void> thenRunAsync(Runnable action);
   public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
 * thenRun它的入参是一个Runnable的实例,表示当得到上一步的结果时的操作。但是对上一步的计算结果不关心,执行下一个操作。
 */
@Test
public void testThenRun() {
    CompletableFuture.supplyAsync(()->"hello ").thenRun(()-> System.out.println("hello Mr.Lee"));
}
/**
 * public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
   public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
   public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);
 * 结合两个CompletionStage的结果,进行转化后返回
 */
@Test
public void testCombine() {
    String join = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello";
    }).thenCombine(CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "world";
    }), (s1, s2) -> s1 + s2).join();
    System.out.println(join);
}
/**
 * public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
   public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
   public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action,     Executor executor);
 * thenAcceptBoth结合两个CompletionStage的结果,进行消耗,它需要原来的处理返回值,并且other代表的CompletionStage也要返回值之后,利用这两个返回值,进行消耗。
 */
@Test
public void testThenAcceptBoth() {
    CompletableFuture.supplyAsync(()->{
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello";
    }).thenAcceptBoth(CompletableFuture.supplyAsync(()->{
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "world";
    }), (s1, s2) -> System.out.println(s1 + " " + s2));
    while (true){}
}
/**
 * public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
   public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);
   public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor);
 * runAfterBoth在两个CompletionStage都运行完执行。不关心这两个CompletionStage的结果,只关心这两个CompletionStage执行完毕,之后在进行操作(Runnable)。
 */
@Test
public void testRunAfterBoth() {
    CompletableFuture.supplyAsync(()->{
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello";
    }).runAfterBothAsync(CompletableFuture.supplyAsync(()->{
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "world";
    }),()-> System.out.println("我来啦"));
}
/**
 * public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn);
   public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn);
   public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor);
 * 两个CompletionStage,谁计算的快,我就用那个CompletionStage的结果进行下一步的转化操作。
 */
@Test
public void testApplyToEither() {
    String result = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "s1";
    }).applyToEither(CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello world";
    }), s -> s).join();
    System.out.println(result);
}
/**
 * public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action);
   public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);
   public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor);
 * 两个CompletionStage,谁计算的快,我就用那个CompletionStage的结果进行下一步的消耗操作。
 */
@Test
public void acceptEither() {
    CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "s1";
    }).acceptEither(CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello world";
    }), System.out::println);
    while (true){}
}
/**
 * public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action);
   public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);
   public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);
 * 两个CompletionStage,任何一个完成了都会执行下一步的操作(Runnable)
 */
@Test
public void runAfterEither() {
    CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "s1";
    }).runAfterEither(CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "s2";
    }), () -> System.out.println("hello world"));
    while (true) {
    }
}
/**
 * public CompletionStage<T> exceptionally(Function<Throwable, ? extends T> fn);
 * 当运行时出现了异常,可以通过exceptionally进行补偿
 */
@Test
public void testExceptionally() {
    String join = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (true) {
            throw new RuntimeException("简单测一下异常");
        }
        return "s";
    }).exceptionally(s -> {
        System.out.println(s.getMessage());
        return "hello world";
    }).join();
    System.out.println(join);
}
/**
 * public CompletionStage<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
   public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
   public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action,Executor executor);
 * 当运行完成时,对结果的记录。这里的完成时有两种情况,一种是正常执行,返回值。
 * 另外一种是遇到异常抛出造成程序的中断。这里为什么要说成记录,因为这几个方法都会返回CompletableFuture,
 * 当Action执行完毕后它的结果返回原始的CompletableFuture的计算结果或者返回异常。所以不会对结果产生任何的作用。
 */
@Test
public void whenComplete() {
    String result = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (1 == 1) {
            throw new RuntimeException("测试一下异常情况");
        }
        return "s1";
    }).whenComplete((s, t) -> {
        System.out.println(s);
        System.out.println(t.getMessage());
    }).exceptionally(e -> {
        System.out.println(e.getMessage());
        return "hello world";
    }).join();
    System.out.println(result);
}
/**
 * public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);
   public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
   public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Executor executor);
 * 运行完成时,对结果的处理。这里的完成时有两种情况,一种是正常执行,返回值。
 * 另外一种是遇到异常抛出造成程序的中断。
 */
@Test
public void handle() {
    String result = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //出现异常
        if (1 == 1) {
            throw new RuntimeException("测试一下异常情况");
        }
        return "s1";
    }).handle((s, t) -> {
        if (t != null) {
            return "hello world";
        }
        return s;
    }).join();
    System.out.println(result);
}

参考:https://www.jianshu.com/p/6f3ee90ab7d3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值