JUC并发编程—— CompletableFuture 实现异步回调

本文介绍了 Java 8 中 CompletableFuture 的使用方法,包括如何创建异步任务并利用 whenComplete 和 exceptionally 方法来处理任务的正常执行结果及异常情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JUC并发编程—— CompletableFuture 实现异步回调

1、CompletableFuture

异步回调

异步回调指的是:在发起一个异步任务的同时指定一个函数,在异步任务完成时会自动的调用这个函数,这个函数就是回调函数。

CompletableFuture

Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在任务执行成功或失败后作出相应的操作。

使用 Future 获得异步执行结果时,要么调用阻塞方法get(),要么轮询看isDone()是否为true,这两种方法都不是很好,因为主线程也会被迫等待。

从Java 8开始引入了 CompletableFuture,它针对 Future 做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法,CompletableFuture 是 Future 的实现类。一个completableFuture对象代表着一个任务

CompletableFuture 的优点是:

  • 异步任务结束时,会自动回调某个对象的方法;
  • 异步任务出错时,会自动回调某个对象的方法;
  • 主线程设置好回调后,不再关心异步任务的执行。

2、实现异步回调

2.1、异步任务

创建一个没有返回值的异步任务:

public class Demo01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //runAsync 执行一个异步任务,没有返回值
        CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" ->runAsync->void");
        });
        //获取异步任务的结果
        future.get();
    }
}

runAsync表示创建无返回值的异步任务,该方法有一个重载版本,可以指定执行异步任务的Executor实现,如果不指定,默认使用 ForkJoinPool.commonPool()。

在这里插入图片描述

创建一个有返回值的异步任务:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+" ->supplyAsync->Integer");
    return 1024;
});

supplyAsync表示创建有返回值的异步任务,该方法有一个重载版本,可以指定执行异步任务的Executor实现,如果不指定,默认使用 ForkJoinPool.commonPool()。

在这里插入图片描述

2.2、异步回调

异步回调

创建异步任务执行完后的回调方法:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+" ->supplyAsync->Integer");
    //如果任务正常执行返回1024
    return 1024;
});

//回调函数
CompletableFuture<Integer> whenComplete = future.whenComplete((t,u)->{
    //打印两个参数
    System.out.println("t->"+t);
    System.out.println("u->"+u);
}).exceptionally((e)->{
    System.out.println(e.getMessage());
    //如果任务执行异常则返回500
    return 500;
});
System.out.println(whenComplete.get());//获取异步任务的结果

whenComplete() :当某个任务执行完成后执行的回调方法,当CompletableFuture完成计算结果时对结果进行处理,或者当CompletableFuture产生异常的时候对异常进行处理。

whenComplete() 源码:

    public CompletableFuture<T> whenComplete(
        BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(null, action);
    }

    public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(asyncPool, action);
    }

    public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action, Executor executor) {
        return uniWhenCompleteStage(screenExecutor(executor), action);
    }

whenComplete 和 whenCompleteAsync 的区别:

whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。

whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。

可以看到Action的类型是BiConsumer<? super T,? super Throwable>它可以处理正常的计算结果,或者异常情况。

BiConsumer 可以接收两个参数:

在这里插入图片描述

exceptionally方法指定某个任务执行异常时执行的回调方法,会将抛出异常作为参数传递到回调方法中,如果该任务正常执行则exceptionally方法返回的result就是该任务正常执行的结果。

在这里插入图片描述

查看上面任务正常执行时,回调函数的执行结果和参数的输出:

在这里插入图片描述

查看任务异常执行时,两个参数的输出:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+" ->supplyAsync->Integer");
    int i = 10 / 0;
    return 1024;
});

在这里插入图片描述

whenComplete会将异步任务执行结果或者执行期间抛出的异常传递给回调方法,

如果任务正常执行:get方法输出正常执行结果,异常输出为null

如果任务执行出现异常:get方法输出异常执行结果,并打印异常信息,无正常结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

万里顾—程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值