提到CompletableFuture就需要先提到Future,Future就是Java里的一个接口,代表异步计算返回的结果,获取方式就是通过线程池提交Callable或Runnable任务返回,但是呢调用get()会阻塞当前线程,知道任务完成

获取结果:通过 get() 方法获取任务执行结果。如果任务还没完成,调用 get() 会阻塞当前线程,直到任务完成。你也可以使用带超时参数的 get(long timeout, TimeUnit unit) 方法,避免长时间阻塞。

取消任务:使用 cancel(boolean mayInterruptIfRunning) 方法尝试取消任务。

检查状态:isDone() 方法判断任务是否已完成(包括正常结束、异常或取消),isCancelled() 方法则判断任务是否已被取消

Future使用代码示例:

public class FutureExample {

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newFixedThreadPool(2);

// 提交Callable任务,返回Future

        Future<String> future = executor.submit(() -> {

            Thread.sleep(2000);

            return "Hello from Future!";

        });



        System.out.println("Do something else while task is running...");

// get()会阻塞,直到任务完成并返回结果

        String result = future.get();

        System.out.println(result);



        executor.shutdown();

    }

}

Java8就引入了CompletableFuture,一个强大的异步编程工具。允许非阻塞地处理异步任务,并且可以通过链式调用组合多个异步操作,CompletableFuture是Future的升级版,Future能做的它都能做

CompletableFuture 的核心优势在于它实现了 CompletionStage 接口,这让它拥有了链式调用和任务组合的能力。

为了方便理解,这里举个例子:

回调:

我们想要去一家餐厅吃饭,餐厅通常会取号然后让你等待,当菜做好了就会通知你,在这个等待的过程中你可以做自己的事,这叫做异步

Future.get()就好像是餐厅叫到你号时,你去取餐的那个动作,这时候餐还没做好(任务未完成),就会原地等待(线程阻塞),直到餐做好了,你才能够去拿到餐,这个过程你只能返回询问是否做好(isDone())或干脆阻塞等待。

CompletableFuture允许你预定回调函数(thenAccept),出结果后则通知你

示例代码:

public class CompletableFutureRestaurantExample {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 模拟一个餐厅的后厨线程池
        // 实际开发中,建议根据业务需求使用自定义线程池,而非默认的ForkJoinPool.commonPool()
        
        // 厨师开始烹饪主菜(异步任务,有返回值)
        CompletableFuture<String> mainDishFuture = CompletableFuture.supplyAsync(() -> {
            try {
                System.out.println("【厨师】开始烹饪主菜:红烧狮子头...(线程: " + Thread.currentThread().getName() + ")");
                Thread.sleep(3000); // 模拟烹饪耗时
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return "红烧狮子头";
        });

        // 同时准备凉菜(另一个异步任务,有返回值)
        CompletableFuture<String> coldDishFuture = CompletableFuture.supplyAsync(() -> {
            try {
                System.out.println("【厨师】开始准备凉菜:凉拌黄瓜...(线程: " + Thread.currentThread().getName() + ")");
                Thread.sleep(1500); // 模拟准备耗时
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return "凉拌黄瓜";
        });

        // 异步组合任务:等主菜和凉菜都做好后,开始准备套餐
        CompletableFuture<String> mealFuture = mainDishFuture
                .thenCombineAsync(coldDishFuture, (mainDish, coldDish) -> {
                    System.out.println("【厨师】开始组合套餐: " + mainDish + " + " + coldDish + "(线程: " + Thread.currentThread().getName() + ")");
                    return "套餐: " + mainDish + " + " + coldDish;
                });
        
        // 定义异常处理:如果任何一道菜制作失败,提供默认菜品
        CompletableFuture<String> exceptionHandledFuture = mealFuture.exceptionally(ex -> {
            System.err.println("【后厨】制作过程中出现异常,提供默认套餐: " + ex.getMessage());
            return "默认套餐(炒饭+酸辣汤)";
        });

        // 最终消费结果:通知顾客取餐
        exceptionHandledFuture.thenAccept(meal -> {
            System.out.println("【服务员】餐已准备好: " + meal + ",请顾客取餐!(线程: " + Thread.currentThread().getName() + ")");
        });

        // 主线程(模拟顾客等待)
        System.out.println("【顾客】已下单,在座位上玩手机...(线程: " + Thread.currentThread().getName() + ")");
        
        // 为了演示,主线程等待所有异步任务完成(实际生产中可能不会这样)
        exceptionHandledFuture.get(); // 或者使用 join()
        System.out.println("【顾客】收到通知,前往取餐。");
    }
}

任务组合:

Future很难处理多个异步任务的依赖关系,CompletableFuture提供了ompletableFuture 提供了 thenCombine(等两个任务都完成再处理)、thenCompose(第一个任务的结果作为第二个任务的输入)、allOf(等所有任务完成)、anyOf(等任意一个任务完成) 等方法,轻松编排复杂异步流程

异常处理:

Future的异常需在get()时使用try-catch捕获ExcutionException,而CompletableFuture提供了exceptionally、handle等方法,可以处理链式中任何阶段的异常

手动完成:Future 不能手动设置结果。CompletableFuture 可以通过 complete()completeExceptionally() 手动设置结果或异常

总结:

CompletableFuture在Future的基础上,提供了更强大的异步任务编排和处理能力,不需要阻塞主线程,同时处理多个任务,让异步编程更流畅

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐