You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建仅在调用CompletableFuture::get时才执行计算的CompletableFuture?

实现CompletableFuture的惰性求值

CompletableFuture默认调用supplyAsync这类方法时会立刻把任务提交到线程池执行,要实现调用get()/join()时才启动计算的惰性效果,你可以试试这几种方式:

  • 用Supplier+缓存封装按需执行逻辑
    先把计算逻辑放在Supplier里,不直接创建CompletableFuture,直到需要获取结果时才触发任务,同时加个缓存避免重复执行:

    // 定义耗时的计算逻辑
    private Supplier<String> lazyCompute = () -> {
        // 这里写你的计算代码
        return "计算完成的结果";
    };
    private CompletableFuture<String> cachedFuture;
    
    public String getLazyResult() throws InterruptedException, ExecutionException {
        if (cachedFuture == null) {
            // 第一次调用get时才启动任务
            cachedFuture = CompletableFuture.supplyAsync(lazyCompute);
        }
        return cachedFuture.get();
    }
    

    这种方式不用自定义类,代码简单,适合大多数场景。

  • 自定义惰性CompletableFuture子类
    如果需要更通用的封装,可以自己写一个子类,重写get/join方法,确保只有在调用这些方法时才启动计算:

    public class LazyCompletableFuture<T> extends CompletableFuture<T> {
        private final Supplier<T> task;
        private volatile boolean isStarted = false;
    
        public LazyCompletableFuture(Supplier<T> task) {
            this.task = task;
        }
    
        @Override
        public T get() throws InterruptedException, ExecutionException {
            startTaskIfNeeded();
            return super.get();
        }
    
        @Override
        public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            startTaskIfNeeded();
            return super.get(timeout, unit);
        }
    
        @Override
        public T join() {
            startTaskIfNeeded();
            return super.join();
        }
    
        private void startTaskIfNeeded() {
            if (!isStarted) {
                synchronized (this) {
                    if (!isStarted) {
                        // 启动任务并把结果/异常传递给当前Future
                        CompletableFuture.supplyAsync(task)
                            .whenComplete((result, ex) -> {
                                if (ex != null) {
                                    completeExceptionally(ex);
                                } else {
                                    complete(result);
                                }
                            });
                        isStarted = true;
                    }
                }
            }
        }
    }
    

    使用时直接实例化,调用get之前任务不会执行:

    LazyCompletableFuture<String> lazyFuture = new LazyCompletableFuture<>(() -> "惰性计算结果");
    // 此时任务未启动
    String result = lazyFuture.get(); // 调用get时才开始计算
    
  • 第三方替代方案(可选)
    如果允许引入外部依赖,Guava的ListenableFuture天生支持惰性执行,需要手动绑定Executor来触发任务,不过如果不想加依赖,前面两种原生方案足够用。

内容的提问来源于stack exchange,提问作者davidalayachew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:30:09