CompletableFutuer异步回调

CompletableFuture的类关系

对于 Future接口都比较熟悉了.主要介绍下CompletionStage接口.

CompletionStage接口代表异步计算过程中的某一个阶段,一个阶段完成后会进入另一个阶段.一个阶段可以理解为一个子任务,每个子任务会包装一个Java函数式接口实例,表示该子任务要执行的操作.

CompletionStage接口

顾名思义,Stage是阶段的意思.CompletionStage代表某个同步或者异步计算的一个阶段,或者是一系列异步任务中的一个子任务.

每个CompletionStage子任务所包装的可以是一个Function Consumer Runnable函数式接口.

1:Function

Function接口的特点,有输入有输出,包装了Function实例的CompletionStage的子任务需要输入一个参数,并会产生一个输出结果到下一步.

2:Runnable

Runnable接口的特点,是无输入无输出,包装了Runnable实例的CompletionStage的子任务既不需要任何输入也不会产生任何输出.

3:Consumer

Consumer接口的特点是,有输入无输出.包装了Consumer实例的CompletionStage的子任务需要输入一个参数,但不会产生任何输出.

runAsync和supplyAsync创建子任务

CompletionStage子任务的创建是通过CompletableFuture完成的.CompletableFuture定义了一组方法用于创建CompletionStage子任务.基础方法如下.

 //包装一个Runnable实例,使用ForkJoinPool.commonPool()线程池来执行
 public static CompletableFuture<Void> runAsync(Runnable runnable)

 //包装一个Runnable实例,指定线程池执行.
 public static CompletableFuture<Void> runAsync(Runnable runnable,
                                                   Executor executor) 
 
 //包装一个Supplier实例,使用ForkJoinPool.commonPool()线程池来执行
 public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)

 //包装一个Supplier实例,指定线程池执行.
 public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                       Executor executor)

实例如下

public class CompletableFutureTest {

    public static void main(String[] args) throws Exception {
        //创建一个无输入值无返回值的异步子任务.
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("运行结束");
            }
        });
        //等待异步任务执行完成.
        future.get(2, TimeUnit.SECONDS);

        //创建一个无输入有返回值的异步子任务.
        CompletableFuture<Long> future1 = CompletableFuture.supplyAsync(() -> {
            long start = System.currentTimeMillis();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("运行结束");
            }
            return System.currentTimeMillis() - start;
        });
        //等待异步任务执行完成.
        Long aLong = future1.get(2, TimeUnit.SECONDS);
        System.out.println("异步执行耗时--" + aLong / 1000);
    }
}
设置子任务的回调钩子

 可以为CompletionStage子任务设置特定的回调钩子,当计算计算结果完成或者抛出异常的时候执行这些特定的回调钩子.

//设置子任务完成的回调钩子.
public CompletableFuture<T> whenComplete(
        BiConsumer<? super T, ? super Throwable> action)

//设置子任务完成的回调钩子,可能不在同一个线程.
public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action)

//设置子任务完成的回调钩子,提交给线程池执行.
public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action, Executor executor)

实例如下

public class CompletableFutureTest2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("发生异常");
            throw new RuntimeException("我是异常..");
        });
        
        //异步执行完成的回调钩子.
        future.whenComplete(new BiConsumer<Void, Throwable>() {
            @Override
            public void accept(Void unused, Throwable throwable) {
                System.out.println("执行完成.");
            }
        });
        //抛出异常回调钩子.
        future.exceptionally(new Function<Throwable, Void>() {
            @Override
            public Void apply(Throwable throwable) {
                System.out.println("执行失败"+throwable.getMessage());
                return null;
            }
        });
        
        //异步获取结果.
        System.out.println(future.get());
    }
}
调用Handle()方法统一处理异常和结果

除了可以通过回调函数处理以外,还可以通过handle方法统一处理结果和异常.

handle方法有三个重载版本.

//在执行任务的同一个线程处理异常和结果.
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 class CompletableFutureTest3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("发生异常");
            throw new RuntimeException("我是异常..");
        });

        future.handle(new BiFunction<Void, Throwable, Object>() {
            @Override
            public Object apply(Void unused, Throwable throwable) {
                if (null == throwable) {
                    System.out.println("没有发生异常.");
                }else {
                    System.out.println("发生了异常.");
                }
                return null;
            }
        });

        System.out.println(future.get());
    }
}

走的多了自然就成了路.我走在四下无人的地方,我何来路可选,何来言弃一说.

如果大家喜欢我的分享的话.关注下我的微信公众号

心有九月星辰


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值