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 并发编程中的重要工具。

相关推荐
java1234_小锋几秒前
Java高频面试题:Spring-AOP通知和执行顺序?
java·开发语言·spring
番茄去哪了4 分钟前
Java基础面试题day02
java·开发语言·面向对象编程
我是咸鱼不闲呀20 分钟前
力扣Hot100系列22(Java)——[图论]总结(岛屿数量,腐烂的橘子,课程表,实现Trie(前缀树))
java·leetcode·图论
1104.北光c°21 分钟前
深入浅出 Elasticsearch:从搜索框到精准排序的架构实战
java·开发语言·elasticsearch·缓存·架构·全文检索·es
MSTcheng.26 分钟前
【优选算法必修篇——位运算】『面试题 01.01. 判定字符是否唯一&面试题 17.19. 消失的两个数字』
java·算法·面试
蹦哒29 分钟前
Kotlin 与 Java 语法差异
java·python·kotlin
左左右右左右摇晃29 分钟前
Java并发——并发编程底层原理
java·开发语言
一个有温度的技术博主35 分钟前
Redis系列八:Jedis连接池在java中的使用
java·redis·bootstrap
cyforkk37 分钟前
Java 并发编程教科书级范例:深入解析 computeIfAbsent 与方法引用
java·开发语言
后青春期的诗go40 分钟前
泛微OA-E9与第三方系统集成开发企业级实战记录(八)
java·接口·金蝶·泛微·oa·集成开发·对接