Java CompletableFuture 使用详解

Java CompletableFuture 使用详解

CompletableFuture 是 Java 8 引入的异步编程工具,它实现了 FutureCompletionStage 接口,提供了强大的异步编程能力。

1. 基础创建方式

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

public class CompletableFutureBasics {
    
    // 1. 直接创建已完成的 Future
    public static void completedFutureExample() {
        CompletableFuture<String> future = CompletableFuture.completedFuture("Hello");
        try {
            System.out.println(future.get()); // 输出: Hello
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // 2. 使用 runAsync 执行无返回值的异步任务
    public static void runAsyncExample() {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("异步任务执行中...");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务完成");
        });
        
        future.join(); // 等待任务完成
    }
    
    // 3. 使用 supplyAsync 执行有返回值的异步任务
    public static void supplyAsyncExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "异步任务结果";
        });
        
        try {
            String result = future.get(); // 阻塞获取结果
            System.out.println("结果: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 回调处理(链式操作)

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class CallbackExample {
    
    public static void thenApplyExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello";
        });
        
        // thenApply: 转换结果
        CompletableFuture<String> greetingFuture = future.thenApply(s -> s + " World");
        
        // thenAccept: 消费结果,无返回值
        greetingFuture.thenAccept(s -> System.out.println("结果: " + s));
        
        // thenRun: 任务完成后执行,不关心结果
        greetingFuture.thenRun(() -> System.out.println("任务完成"));
        
        greetingFuture.join();
    }
    
    public static void thenComposeExample() {
        // thenCompose: 组合两个 Future,第二个依赖于第一个的结果
        CompletableFuture<String> future = getUserInfo("123")
            .thenCompose(user -> getOrderInfo(user));
        
        future.thenAccept(System.out::println).join();
    }
    
    private static CompletableFuture<String> getUserInfo(String userId) {
        return CompletableFuture.supplyAsync(() -> "用户" + userId);
    }
    
    private static CompletableFuture<String> getOrderInfo(String user) {
        return CompletableFuture.supplyAsync(() -> user + "的订单信息");
    }
}

3. 组合多个 Future

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class CombineExample {
    
    public static void thenCombineExample() {
        // thenCombine: 组合两个独立的 Future
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello";
        });
        
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "World";
        });
        
        // 组合两个结果
        CompletableFuture<String> combined = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
        
        System.out.println(combined.join()); // 输出: Hello World
    }
    
    public static void allOfExample() {
        // allOf: 等待所有 Future 完成
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "结果1");
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "结果2");
        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "结果3");
        
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);
        
        allFutures.thenRun(() -> {
            try {
                System.out.println("所有任务完成: " + future1.get() + ", " + future2.get() + ", " + future3.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).join();
    }
    
    public static void anyOfExample() {
        // anyOf: 任意一个 Future 完成即可
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "结果1";
        });
        
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "结果2";
        });
        
        CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
        
        System.out.println("最先完成的结果: " + anyFuture.join()); // 输出: 结果2
    }
}

4. 异常处理

java 复制代码
import java.util.concurrent.CompletableFuture;

public class ExceptionHandlingExample {
    
    public static void exceptionallyExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("发生异常");
            }
            return "正常结果";
        });
        
        // exceptionally: 发生异常时提供默认值
        CompletableFuture<String> safeFuture = future.exceptionally(ex -> {
            System.out.println("捕获异常: " + ex.getMessage());
            return "默认值";
        });
        
        System.out.println(safeFuture.join()); // 输出: 默认值
    }
    
    public static void handleExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 这里可能会成功,也可能会失败
            return "正常结果";
            // throw new RuntimeException("发生异常");
        });
        
        // handle: 无论成功还是失败都会执行
        CompletableFuture<String> handledFuture = future.handle((result, ex) -> {
            if (ex != null) {
                return "异常处理结果";
            }
            return "处理后的: " + result;
        });
        
        System.out.println(handledFuture.join());
    }
    
    public static void whenCompleteExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // throw new RuntimeException("测试异常");
            return "成功结果";
        });
        
        // whenComplete: 任务完成后执行,可获取结果和异常
        future.whenComplete((result, ex) -> {
            if (ex != null) {
                System.out.println("任务异常: " + ex.getMessage());
            } else {
                System.out.println("任务成功: " + result);
            }
        }).join();
    }
}

5. 超时处理(Java 9+)

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class TimeoutExample {
    
    public static void orTimeoutExample() {
        // orTimeout: Java 9+ 的超时方法
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "慢任务结果";
        }).orTimeout(1, TimeUnit.SECONDS) // 设置1秒超时
          .exceptionally(ex -> {
              if (ex instanceof TimeoutException) {
                  return "超时,返回默认值";
              }
              return "其他异常";
          });
        
        System.out.println(future.join()); // 输出: 超时,返回默认值
    }
    
    public static void completeOnTimeoutExample() {
        // completeOnTimeout: 超时时完成并返回默认值
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "慢任务结果";
        }).completeOnTimeout("超时默认值", 1, TimeUnit.SECONDS);
        
        System.out.println(future.join()); // 输出: 超时默认值
    }
}

6. 实际应用示例

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

public class PracticalExample {
    
    // 自定义线程池
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);
    
    public static void parallelTasksExample() {
        List<String> ids = List.of("1", "2", "3", "4", "5");
        
        // 并行查询多个ID的信息
        List<CompletableFuture<String>> futures = ids.stream()
            .map(id -> CompletableFuture.supplyAsync(() -> queryDatabase(id), executor))
            .collect(Collectors.toList());
        
        // 等待所有查询完成
        List<String> results = futures.stream()
            .map(CompletableFuture::join)
            .collect(Collectors.toList());
        
        System.out.println("查询结果: " + results);
    }
    
    private static String queryDatabase(String id) {
        try {
            TimeUnit.MILLISECONDS.sleep(500); // 模拟数据库查询
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "数据" + id;
    }
    
    public static void pipelineExample() {
        // 构建处理流水线
        CompletableFuture<String> pipeline = CompletableFuture
            .supplyAsync(() -> "原始数据", executor)
            .thenApplyAsync(data -> data + " -> 步骤1处理", executor)
            .thenApplyAsync(data -> data + " -> 步骤2处理", executor)
            .thenApplyAsync(data -> data + " -> 步骤3处理", executor)
            .thenApplyAsync(data -> data + " -> 完成", executor);
        
        System.out.println("流水线结果: " + pipeline.join());
    }
    
    public static void shutdown() {
        executor.shutdown();
    }
    
    public static void main(String[] args) {
        try {
            parallelTasksExample();
            pipelineExample();
        } finally {
            shutdown();
        }
    }
}

7. 最佳实践

  1. 使用自定义线程池:避免使用默认的 ForkJoinPool,防止影响其他任务
  2. 合理处理异常:使用 exceptionally、handle 等方法处理异常
  3. 避免阻塞:尽量使用 thenApply、thenAccept 等非阻塞方法
  4. 资源清理:及时关闭自定义的 ExecutorService
  5. 避免嵌套过深:保持链式调用的可读性

8. 主要方法总结

方法 描述
supplyAsync() 异步执行有返回值的任务
runAsync() 异步执行无返回值的任务
thenApply() 对结果进行转换
thenAccept() 消费结果,无返回值
thenRun() 任务完成后执行,不关心结果
thenCompose() 组合两个有依赖关系的 Future
thenCombine() 组合两个独立的 Future
allOf() 等待所有 Future 完成
anyOf() 任意一个 Future 完成即可
exceptionally() 异常处理
handle() 处理结果和异常
whenComplete() 完成后执行回调

CompletableFuture 使得异步编程变得更加简洁和强大,是 Java 并发编程中的重要工具。

相关推荐
李白的天不白9 小时前
ps -ef | grep java
java
ab_dg_dp9 小时前
Android 17+ 提取 AIDL 生成 Java 文件的实用脚本
android·java·python
超哥--9 小时前
B站视频内容智能分析系统(三):B站视频自动采集
java·开发语言·音视频·ai编程
郑洁文9 小时前
基于SpringBoot的商品仓库管理系统的设计与实现
java·spring boot·后端·仓库管理系统·商品仓库管理系统
布朗克1689 小时前
22 异常处理——从入门到精通的完整指南
java·异常处理
小旭95279 小时前
Spring AI Alibaba 从入门到实战:一站式掌握企业级 AI 应用开发
java·人工智能·spring
Arrom10 小时前
DLNA 渲染端排障实战:从 20s 卡顿到 stale subscriber 的两周追凶之旅
android·java
J-Tony1110 小时前
【JVM】三色标记法
java·jvm·算法
李白的天不白10 小时前
docker ps
java
NE_STOP11 小时前
Docker--Docker Swarm集群
java