MST

星途 面试题库

面试题:Java中Future接口与CompletableFuture的对比及应用

阐述Java中Future接口和CompletableFuture的主要区别,并且举例说明在一个需要处理多个异步任务,且任务之间存在依赖关系的场景下,如何分别使用Future接口和CompletableFuture来实现。
31.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

主要区别

  1. Future接口
    • Future是Java早期用于异步计算结果获取的接口。它只能通过get()方法阻塞等待任务完成来获取结果,或者通过isDone()方法轮询任务是否完成,缺乏对异步任务完成后的链式操作支持。
    • 对于多个异步任务之间存在依赖关系的场景,Future实现起来比较繁琐,需要手动管理线程间的协作。
  2. CompletableFuture
    • CompletableFuture是Java 8引入的,它扩展了Future接口。它支持异步任务完成后的链式调用,如thenApplythenCompose等方法,方便处理任务间的依赖关系。
    • 可以通过回调机制,在任务完成时自动触发后续操作,无需阻塞等待。

使用示例

Future接口实现

假设我们有两个异步任务,任务B依赖任务A的结果。

import java.util.concurrent.*;

public class FutureExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        Future<Integer> futureA = executor.submit(() -> {
            // 模拟任务A执行
            Thread.sleep(2000);
            return 10;
        });

        Future<Integer> futureB = executor.submit(() -> {
            try {
                // 等待任务A完成并获取结果
                int resultA = futureA.get();
                // 模拟任务B依赖任务A的结果进行计算
                Thread.sleep(2000);
                return resultA * 2;
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
                return -1;
            }
        });

        try {
            System.out.println("任务B的结果: " + futureB.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        executor.shutdown();
    }
}

CompletableFuture实现

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> {
            // 模拟任务A执行
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 10;
        });

        CompletableFuture<Integer> futureB = futureA.thenApplyAsync(resultA -> {
            // 模拟任务B依赖任务A的结果进行计算
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return resultA * 2;
        });

        futureB.thenAccept(System.out::println).join();
    }
}

在上述CompletableFuture示例中,thenApplyAsync方法实现了任务B依赖任务A结果的链式操作,并且无需显式地阻塞等待任务A完成。而在Future示例中,需要手动通过get()方法获取任务A的结果,然后再提交任务B。