CompletableFuture 实际场景使用案例

一、CompletableFuture 概述

1.1 什么是 CompletableFuture?

CompletableFuture 是 Java 8 引入的异步编程工具,实现了 FutureCompletionStage 接口。它提供了强大的异步编程能力,支持函数式编程风格,可以方便地组合多个异步操作。

1.2 核心特性

  • 异步执行:支持异步任务执行

  • 链式调用:可以串联多个异步操作

  • 组合操作:支持多个异步任务的组合(AND、OR)

  • 异常处理:提供完善的异常处理机制

  • 手动完成:可以手动完成 Future

二、基本使用方式

2.1 创建 CompletableFuture

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompletableFutureBasic {
    
    // 1. 使用默认线程池创建
    public static void createFuture() {
        // 有返回值的异步任务
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello from async task";
        });
        
        // 无返回值的异步任务
        CompletableFuture<Void> runFuture = CompletableFuture.runAsync(() -> {
            System.out.println("Task is running...");
        });
    }
    
    // 2. 使用自定义线程池
    public static void createWithCustomExecutor() {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 长时间运行的任务
            return "Result";
        }, executor);
        
        executor.shutdown();
    }
}

三、核心方法详解

3.1 结果处理

java 复制代码
public class ResultHandling {
    
    // thenApply: 转换结果
    public static void thenApplyExample() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
            .thenApply(s -> s + " World")
            .thenApply(String::toUpperCase);
        
        System.out.println(future.get()); // 输出: HELLO WORLD
    }
    
    // thenAccept: 消费结果
    public static void thenAcceptExample() {
        CompletableFuture.supplyAsync(() -> "Hello")
            .thenAccept(result -> System.out.println("Result: " + result));
    }
    
    // thenRun: 完成后执行操作
    public static void thenRunExample() {
        CompletableFuture.supplyAsync(() -> {
            System.out.println("Task executing...");
            return "Done";
        }).thenRun(() -> System.out.println("Task completed"));
    }
    
    // handle: 处理结果和异常
    public static void handleExample() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("Error!");
            }
            return 10;
        }).handle((result, ex) -> {
            if (ex != null) {
                System.out.println("Exception occurred: " + ex.getMessage());
                return -1; // 返回默认值
            }
            return result;
        });
        
        System.out.println(future.get()); // 输出: -1
    }
    
    // exceptionally: 异常处理
    public static void exceptionallyExample() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            throw new RuntimeException("Calculation error");
        }).exceptionally(ex -> {
            System.err.println("Error: " + ex.getMessage());
            return 0; // 返回默认值
        });
        
        System.out.println(future.get()); // 输出: 0
    }
}

3.2 组合多个 Future

java 复制代码
public class CombineFutures {
    
    // thenCompose: 链式组合(上一个结果作为下一个的输入)
    public static void thenComposeExample() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = getUserInfo(1)
            .thenCompose(userId -> getUserDetails(userId));
        
        System.out.println(future.get());
    }
    
    // thenCombine: 合并两个独立 Future 的结果
    public static void thenCombineExample() throws ExecutionException, InterruptedException {
        CompletableFuture<Double> priceFuture = getPrice();
        CompletableFuture<Double> taxRateFuture = getTaxRate();
        
        CompletableFuture<Double> totalFuture = priceFuture.thenCombine(
            taxRateFuture, (price, taxRate) -> price * (1 + taxRate)
        );
        
        System.out.println("Total price: " + totalFuture.get());
    }
    
    // allOf: 等待所有 Future 完成
    public static void allOfExample() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Result1");
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Result2");
        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "Result3");
        
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);
        
        allFutures.thenRun(() -> {
            try {
                System.out.println("All completed: " + future1.get() + ", " 
                    + future2.get() + ", " + future3.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).get();
    }
    
    // anyOf: 任意一个完成即可
    public static void anyOfExample() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            sleep(2000);
            return "Result1";
        });
        
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            sleep(1000);
            return "Result2";
        });
        
        CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
        System.out.println("First completed: " + anyFuture.get()); // 输出: Result2
    }
    
    // 辅助方法
    private static CompletableFuture<String> getUserInfo(int id) {
        return CompletableFuture.supplyAsync(() -> "User" + id);
    }
    
    private static CompletableFuture<String> getUserDetails(String userId) {
        return CompletableFuture.supplyAsync(() -> "Details for " + userId);
    }
    
    private static CompletableFuture<Double> getPrice() {
        return CompletableFuture.supplyAsync(() -> 100.0);
    }
    
    private static CompletableFuture<Double> getTaxRate() {
        return CompletableFuture.supplyAsync(() -> 0.1);
    }
    
    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

四、实际场景使用案例

4.1 场景一:并行调用多个微服务

java 复制代码
public class MicroserviceIntegration {
    
    /**
     * 电商订单处理:并行获取用户信息、商品信息、库存信息
     */
    public CompletableFuture<OrderResult> processOrderAsync(String orderId) {
        // 并行调用多个服务
        CompletableFuture<UserInfo> userFuture = getUserInfoAsync(orderId);
        CompletableFuture<ProductInfo> productFuture = getProductInfoAsync(orderId);
        CompletableFuture<InventoryInfo> inventoryFuture = getInventoryInfoAsync(orderId);
        
        // 合并所有结果
        return CompletableFuture.allOf(userFuture, productFuture, inventoryFuture)
            .thenApply(v -> {
                try {
                    UserInfo user = userFuture.get();
                    ProductInfo product = productFuture.get();
                    InventoryInfo inventory = inventoryFuture.get();
                    
                    return new OrderResult(user, product, inventory);
                } catch (Exception e) {
                    throw new CompletionException(e);
                }
            })
            .exceptionally(ex -> {
                // 统一异常处理
                log.error("Order processing failed", ex);
                return OrderResult.failed(ex.getMessage());
            });
    }
    
    private CompletableFuture<UserInfo> getUserInfoAsync(String orderId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟调用用户服务
            sleep(200);
            return new UserInfo("user123", "John Doe");
        });
    }
    
    private CompletableFuture<ProductInfo> getProductInfoAsync(String orderId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟调用商品服务
            sleep(150);
            return new ProductInfo("product456", "Laptop", 999.99);
        });
    }
    
    private CompletableFuture<InventoryInfo> getInventoryInfoAsync(String orderId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟调用库存服务
            sleep(100);
            return new InventoryInfo("product456", 10);
        });
    }
    
    // 数据类
    static class OrderResult {
        UserInfo user;
        ProductInfo product;
        InventoryInfo inventory;
        
        // 构造方法、getter/setter...
    }
}

4.2 场景二:超时控制和回退

java 复制代码
public class TimeoutAndFallback {
    
    /**
     * 带超时和降级的服务调用
     */
    public CompletableFuture<String> callServiceWithTimeout() {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        
        // 主服务调用
        CompletableFuture<String> mainService = CompletableFuture.supplyAsync(() -> {
            sleep(3000); // 模拟慢服务
            return "Main Service Response";
        }, executor);
        
        // 超时控制
        CompletableFuture<String> timeout = CompletableFuture.supplyAsync(() -> {
            sleep(2000);
            return "Timeout Fallback";
        }, executor);
        
        // 使用 applyToEither 实现超时控制
        return mainService.applyToEither(timeout, response -> {
            if (response.equals("Timeout Fallback")) {
                // 调用降级服务
                return callFallbackService();
            }
            return response;
        });
    }
    
    /**
     * 使用 CompletableFuture 原生超时(Java 9+)
     */
    public CompletableFuture<String> callWithTimeoutJava9() {
        return CompletableFuture.supplyAsync(() -> {
            sleep(3000);
            return "Service Response";
        })
        .orTimeout(2, TimeUnit.SECONDS) // Java 9+ 方法
        .exceptionally(ex -> callFallbackService());
    }
    
    private String callFallbackService() {
        return "Fallback Service Response";
    }
}

4.3 场景三:批量异步处理

java 复制代码
public class BatchProcessing {
    
    /**
     * 批量异步处理数据
     */
    public CompletableFuture<List<ProcessResult>> batchProcess(List<String> dataList) {
        List<CompletableFuture<ProcessResult>> futures = dataList.stream()
            .map(this::processSingleItemAsync)
            .collect(Collectors.toList());
        
        // 转换 List<CompletableFuture<T>> 为 CompletableFuture<List<T>>
        return sequence(futures);
    }
    
    /**
     * 限制并发数的批量处理
     */
    public CompletableFuture<List<ProcessResult>> batchProcessWithLimit(
            List<String> dataList, int maxConcurrency) {
        
        ExecutorService limitedExecutor = Executors.newFixedThreadPool(maxConcurrency);
        
        List<CompletableFuture<ProcessResult>> futures = dataList.stream()
            .map(data -> CompletableFuture.supplyAsync(
                () -> processItem(data), limitedExecutor))
            .collect(Collectors.toList());
        
        limitedExecutor.shutdown();
        return sequence(futures);
    }
    
    /**
     * 将 List<CompletableFuture<T>> 转换为 CompletableFuture<List<T>>
     */
    private <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futures) {
        CompletableFuture<Void> allDoneFuture = 
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        
        return allDoneFuture.thenApply(v ->
            futures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList())
        );
    }
    
    private ProcessResult processItem(String data) {
        // 处理单个数据项
        return new ProcessResult(data, "processed");
    }
}

4.4 场景四:流水线处理

java 复制代码
public class PipelineProcessing {
    
    /**
     * 数据处理流水线:下载 -> 转换 -> 存储 -> 通知
     */
    public CompletableFuture<Void> dataProcessingPipeline(String url) {
        return downloadData(url)
            .thenApplyAsync(this::transformData, getTransformExecutor())
            .thenComposeAsync(this::storeData, getIOWriterExecutor())
            .thenAcceptAsync(this::sendNotification, getNotificationExecutor())
            .exceptionally(ex -> {
                log.error("Pipeline failed", ex);
                sendAlert(ex);
                return null;
            });
    }
    
    private CompletableFuture<String> downloadData(String url) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟下载
            return "Downloaded data from " + url;
        });
    }
    
    private String transformData(String data) {
        // 数据转换
        return data.toUpperCase();
    }
    
    private CompletableFuture<String> storeData(String data) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟存储
            return "Stored: " + data;
        });
    }
    
    private void sendNotification(String result) {
        System.out.println("Notification: " + result);
    }
    
    private void sendAlert(Throwable ex) {
        System.err.println("Alert: " + ex.getMessage());
    }
    
    // 不同阶段使用不同的线程池
    private ExecutorService getTransformExecutor() {
        return Executors.newFixedThreadPool(4);
    }
    
    private ExecutorService getIOWriterExecutor() {
        return Executors.newFixedThreadPool(2);
    }
    
    private ExecutorService getNotificationExecutor() {
        return Executors.newSingleThreadExecutor();
    }
}

五、最佳实践和注意事项

5.1 最佳实践

java 复制代码
public class BestPractices {
    
    // 1. 始终处理异常
    public void alwaysHandleExceptions() {
        CompletableFuture.supplyAsync(() -> {
            // 业务逻辑
            return "result";
        })
        .exceptionally(ex -> {
            log.error("Task failed", ex);
            return "fallback";
        });
    }
    
    // 2. 使用合适的线程池
    public void useProperThreadPool() {
        ExecutorService cpuBoundExecutor = Executors.newFixedThreadPool(
            Runtime.getRuntime().availableProcessors()
        );
        
        ExecutorService ioBoundExecutor = Executors.newCachedThreadPool();
        
        // CPU 密集型任务
        CompletableFuture.supplyAsync(() -> {
            // 复杂计算
            return compute();
        }, cpuBoundExecutor);
        
        // IO 密集型任务
        CompletableFuture.supplyAsync(() -> {
            // 数据库查询
            return queryDatabase();
        }, ioBoundExecutor);
    }
    
    // 3. 避免阻塞调用
    public CompletableFuture<String> avoidBlockingCalls() {
        return CompletableFuture.supplyAsync(() -> {
            // 错误的做法:在异步任务中阻塞
            // return blockingHttpCall();
            
            // 正确的做法:使用异步客户端
            return asyncHttpClient.get();
        });
    }
    
    // 4. 资源清理
    public void cleanupResources() {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        
        try {
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                return "result";
            }, executor);
            
            String result = future.get(10, TimeUnit.SECONDS);
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
            try {
                if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                executor.shutdownNow();
            }
        }
    }
}

5.2 常见陷阱

java 复制代码
public class CommonPitfalls {
    
    // 1. 忘记调用 get() 或 join()
    public void pitfall1() {
        CompletableFuture.runAsync(() -> {
            System.out.println("Task executed");
        });
        // 如果不调用 get() 或 join(),程序可能直接退出
    }
    
    // 2. 在回调中阻塞
    public void pitfall2() {
        CompletableFuture.supplyAsync(() -> "data")
            .thenApply(data -> {
                // 错误的做法:在回调中进行阻塞操作
                try {
                    Thread.sleep(5000); // 阻塞!
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return data.toUpperCase();
            });
    }
    
    // 3. 异常处理不当
    public void pitfall3() {
        CompletableFuture.supplyAsync(() -> {
            throw new RuntimeException("Error");
        }).thenAccept(result -> {
            // 这里不会执行,因为异常没有被处理
            System.out.println(result);
        });
    }
    
    // 4. 线程池资源泄露
    public void pitfall4() {
        ExecutorService executor = Executors.newCachedThreadPool();
        
        for (int i = 0; i < 1000; i++) {
            CompletableFuture.runAsync(() -> {
                // 任务
            }, executor);
        }
        // 忘记关闭线程池!
    }
}

六、性能监控和调试

java 复制代码
public class CompletableFutureMonitor {
    
    private static final ThreadLocal<Long> startTime = new ThreadLocal<>();
    
    /**
     * 带监控的 CompletableFuture
     */
    public static <T> CompletableFuture<T> monitoredSupplyAsync(
            Supplier<T> supplier, String taskName) {
        
        return CompletableFuture.supplyAsync(() -> {
            startTime.set(System.currentTimeMillis());
            try {
                T result = supplier.get();
                long duration = System.currentTimeMillis() - startTime.get();
                logMetrics(taskName, duration, "SUCCESS");
                return result;
            } catch (Exception e) {
                long duration = System.currentTimeMillis() - startTime.get();
                logMetrics(taskName, duration, "FAILED");
                throw new CompletionException(e);
            } finally {
                startTime.remove();
            }
        });
    }
    
    private static void logMetrics(String taskName, long duration, String status) {
        System.out.printf("Task: %s, Duration: %dms, Status: %s%n", 
            taskName, duration, status);
    }
    
    /**
     * 使用示例
     */
    public void example() {
        monitoredSupplyAsync(() -> {
            sleep(100);
            return "Result";
        }, "dataProcessing").thenAccept(result -> {
            System.out.println("Got result: " + result);
        });
    }
}

总结

CompletableFuture 提供了强大的异步编程能力,适用于:

  1. 微服务调用:并行调用多个服务

  2. 数据处理流水线:链式处理数据

  3. 批量处理:并发处理大量任务

  4. 超时控制:实现服务降级和熔断

  5. 事件驱动架构:响应式编程

关键要点

  • 合理使用线程池,区分 CPU 密集和 IO 密集任务

  • 始终处理异常,避免异常被吞没

  • 注意资源清理,避免内存泄漏

  • 使用适当的超时控制

  • 监控异步任务的执行情况

通过合理使用 CompletableFuture,可以显著提升系统的并发性能和响应能力,同时保持代码的可读性和可维护性。

相关推荐
一念一花一世界2 小时前
Arbess从基础到实践(5) - 集成GitLab+SonarQube搭建Java项目自动化部署
java·gitlab·sonarqube·cicd·arbess
_UMR_2 小时前
多线程场景的学习3,使用CountDownLatch
java·开发语言
无限大.2 小时前
验证码对抗史
java·开发语言·python
明月别枝惊鹊丶2 小时前
【C++】GESP 三级手册
java·开发语言·c++
毕设源码-钟学长2 小时前
【开题答辩全过程】以 公交线路查询系统为例,包含答辩的问题和答案
java
梵得儿SHI2 小时前
SpringCloud - 核心组件精讲:Nacos 深度解析(服务注册 + 配置中心一站式实现)
java·spring boot·spring cloud·nacos·微服务架构的核心组件·服务注册发现与配置管理·nacos的核心原理与实战应用
不如打代码KK3 小时前
Java SPI与Spring Boot SPI的区别
java·开发语言·spring boot
非凡的小笨鱼3 小时前
利用arthas查看java服务里指定对象的大小
java·spring·arthas
代码or搬砖3 小时前
自定义注解全面详解
java·开发语言