CompletableFuture

简介
CompletableFuture能够将回调放到与任务不同的线程中执行,也能将回调作为继续执行的同步函数,在与任务相同的线程中执行。它避免了传统回调最大的问题,那就是能够将控制流分离到不同的事件处理器中。
CompletableFuture弥补了Future模式的缺点。在异步的任务完成后,需要用其结果继续操作时,无需等待。可以直接通过thenAccept、thenApply、thenCompose等方式将前面异步处理的结果交给另外一个异步事件处理线程来处理。
在这里插入图片描述
supplyAsync和runAsync 两者的区别是 runAsync没有返回值 supplyAsync有返回值

allOf

通过join等待指定的线程完成。

 public static List<String> testRun(){
        List<String> list = new ArrayList<>();
        Instant start = Instant.now();
        CompletableFuture<Void> test1 = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(3000);
                list.add("a");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        CompletableFuture<Void> test2 = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(10000);
                list.add("b");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        CompletableFuture<Void> test3 = CompletableFuture.runAsync(() -> {
            list.add("c");
        });
        //保证三个线程都完成!
        CompletableFuture.allOf(test1,test2,test3).join();
        Instant end = Instant.now();
        System.out.println("程序总耗时"+Duration.between(start, end).toMillis());
        System.out.println(list.toString());
        return list;
    }

result:
在这里插入图片描述

complete

complete(T t)方法,完成异步执行,并返回future的结果
* future.get()在等待执行结果时,程序会一直block,如果此时调用complete(T t)会立即执行
* 注意::1 complete的调用至能一次 2 如果future已经执行完毕能够返回结果,此时再调用complete(T t)则会无效

demo

public static void testSupplyAsync() throws Exception {
        Instant start = Instant.now();
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
                return "hello";
            } catch (InterruptedException e) {
                throw new RuntimeException();
            }
        });
        future.complete("word");
        //获取返回值
        String s = future.get();
        Instant end = Instant.now();
        System.out.println(s);
        System.out.println("程序总耗时"+Duration.between(start, end).toMillis());
    }

result
在这里插入图片描述

thenAccept()

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);

功能:当前任务正常完成以后执行,当前任务的执行结果可以作为下一任务的输入参数,无返回值.
场景:任务a执行完成后将结果传入任务b执行,任务b无返回值

   /**
    * 用于消费上一个任务的消费结果 无返回值
     * */
    public static void testThenAccept() throws Exception{
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            return 1;
        }).thenAccept((b) -> {
            System.out.println(b);
        });
    }

thenRun(…)

public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
 

功能:对不关心上一步的计算结果,执行下一个操作

场景:执行任务A,任务A执行完以后,执行任务B,任务B不接受任务A的返回值(不管A有没有返回值),也无返回值
  demo

    /**
     * 对不关心上一步的计算结果,执行下一个操作 无返回值
    * */
    public static void testThenRun(){
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                System.out.println("我是第一个任务");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).thenRunAsync(() -> {
            System.out.println("我执行了");
        });
    }

thenApply(…)

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)

功能:当前任务正常完成以后执行,当前任务的执行的结果会作为下一任务的输入参数,有返回值

场景:多个任务串联执行,下一个任务的执行依赖上一个任务的结果,每个任务都有输入和输出

实例1:异步执行任务A,当任务A完成时使用A的返回结果resultA作为入参进行任务B的处理,可实现任意多个任务的串联执行

/**
     * 当前任务正常完成以后执行,当前任务的执行的结果会作为下一任务的输入参数,有返回值
     * */
    public static void testThenApply() throws Exception{
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
                System.out.println("我是第一个任务");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 1;
        }).thenApply((b) -> {
            return b + 1;
        }).thenApply((c) -> {
            return c + 1;
        });
        future.join(); //future.join()先得到任务A的返回值,然后再拿返回值做入参去执行任务B
        Integer integer = future.get();
    }

thenCombine

public <U,V> CompletableFuture<V>     thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V>     thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V>     thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor)

功能:将两个任务合并
demo:

 /**
     * 将两个任务的返回值结合起来
     * */
    public static void testThenCombiney() throws Exception{
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(10000);
                System.out.println("我是第一个任务");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 1;
        });
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
                System.out.println("我是第一个任务");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 2;
        });
        CompletableFuture<Integer> future3 = future1.thenCombine(future2, (a, b) -> {
            return a + b;
        });
        Integer integer = future3.get();
        System.out.println(integer);
    }
    public static void testThenCombineyTwo() throws Exception{
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(10000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 1;
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 2;
        }), (s1, s2) -> s1 + " " + s2);
        System.out.println(future.get());
    }

runAfterBoth

不关心这两个任务的结果,只关心这两个任务执行完毕,之后在进行操作(Runnable)。
demo:

    public static void testRunAfterBothAsync(){
        Instant start = Instant.now();
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 1;
        }).runAfterBoth(CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(10000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 2;
        }), () -> System.out.println("任务执行完毕"));
        future.join();
        Instant end = Instant.now();
        System.out.println("程序总耗时"+Duration.between(start, end).toMillis());
    }

applyToEither

两个任务,谁计算的快,我就用那个任务的结果进行下一步的转化操作
demo:

 public static void testApplyToEither() {
        String result = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "s1";
        }).applyToEither(CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello world";
        }), s -> s).join();
        System.out.println(result);
    }

runAfterEither

两个任务,任何一个完成了都会执行下一步的操作(Runnable)。
demo:

    /**
    *
     * 两个任务,任何一个完成了都会执行下一步的操作(Runnable)。
     * */
    public static void runAfterEither() throws Exception{
        Instant start = Instant.now();
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(10000);
            } 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"));
        future.join();
        Instant end = Instant.now();
        System.out.println("程序总耗时"+Duration.between(start, end).toMillis());
    }

exceptionally

功能:当运行出现异常时,调用该方法可进行一些补偿操作,如设置默认值.

场景:异步执行任务A获取结果,如果任务A执行过程中抛出异常,则使用默认值100返回.

 /**
    * 当运行时出现了异常,可以通过exceptionally进行补偿。
    * */
    public static void TestExceptionally() {
        String result = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (1 == 1) {
                throw new RuntimeException("测试一下异常情况");
            }
            return "s1";
        }).exceptionally(e -> {
            System.out.println(e.getMessage());
            return "hello world";
        }).join();
        System.out.println(result);
    }

handle

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);

运行完成时,对结果的处理。这里的完成时有两种情况,一种是正常执行,返回值。另外一种是遇到异常抛出造成程序的中断。

    /**
    *
     * 运行完成时,对结果的处理。这里的完成时有两种情况,一种是正常执行,返回值。另外一种是遇到异常抛出造成程序的中断。
     **/
    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.cnblogs.com/fingerboy/p/9948736.html
测试代码:
https://gitee.com/qiu_zheng/completable-future

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值