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

Act Framework中是否有非阻塞式等待Future完成的等效方案?

在Act Framework中实现非阻塞等待Future的方案

好问题!在Act Framework里确实有对应的非阻塞等待方案,和你提到的Play Framework v1的await(future)效果一致,完全能解决控制器线程被阻塞的问题。

核心思路是利用Act对异步返回值的原生支持——控制器方法可以直接返回CompletableFuture<Result>(或者Act封装的Promise<Result>),这样框架会自动释放控制器线程去处理其他请求,直到所有异步任务完成后再用空闲线程处理结果组装和响应。

改造前的阻塞实现(问题代码)

先回顾下你当前的阻塞写法,这里future.get()会直接卡住控制器线程:

public Result myAction() {
    ExecutorService executor1 = ...;
    ExecutorService executor2 = ...;
    Future<String> future1 = executor1.submit(() -> fetchData1());
    Future<String> future2 = executor2.submit(() -> fetchData2());
    
    // 此处阻塞控制器线程,直到任务完成
    String data1 = future1.get();
    String data2 = future2.get();
    
    return ok("Combined: " + data1 + data2);
}

非阻塞改造方案1:使用标准CompletableFuture

Act完全支持标准Java的CompletableFuture作为控制器方法的返回值,我们可以用它来组合多个异步任务,全程不阻塞线程:

import java.util.concurrent.CompletableFuture;
import act.controller.Controller;
import act.http.Http;

public class MyController extends Controller {

    public CompletableFuture<Http.Result> myAction() {
        ExecutorService executor1 = ...;
        ExecutorService executor2 = ...;
        
        // 将原有Future转为CompletableFuture,或者直接用supplyAsync创建
        CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(this::fetchData1, executor1);
        CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(this::fetchData2, executor2);
        
        // 等待所有任务完成后,异步组装结果
        return CompletableFuture.allOf(cf1, cf2)
                .thenApply(ignored -> {
                    // 因为allOf已确保任务完成,此处join()不会阻塞
                    String data1 = cf1.join();
                    String data2 = cf2.join();
                    return ok("Combined: " + data1 + data2);
                });
    }
    
    private String fetchData1() {
        // 你的业务逻辑,比如调用外部服务、数据库查询等
        return "Data from service 1";
    }
    
    private String fetchData2() {
        // 另一项并行执行的业务逻辑
        return "Data from service 2";
    }
}

非阻塞改造方案2:使用Act封装的Promise

如果你更习惯用Act框架自身的异步工具,也可以用Promise(它是对CompletableFuture的轻量封装,API更简洁):

import act.Promise;
import act.controller.Controller;
import act.http.Http;

public class MyController extends Controller {

    public Promise<Http.Result> myAction() {
        ExecutorService executor1 = ...;
        ExecutorService executor2 = ...;
        
        Promise<String> p1 = Promise.supplyAsync(this::fetchData1, executor1);
        Promise<String> p2 = Promise.supplyAsync(this::fetchData2, executor2);
        
        // 等待所有Promise完成后,映射结果为Result
        return Promise.join(p1, p2)
                .map(results -> {
                    String data1 = results[0];
                    String data2 = results[1];
                    return ok("Combined: " + data1 + data2);
                });
    }
    
    // fetchData1、fetchData2方法同上
}

关键注意事项

  • 自定义Executor:尽量使用自己创建的Executor来处理业务异步任务,不要占用Act框架的核心线程池,避免影响框架的请求处理能力。
  • 回调逻辑轻量:在thenApply或map的回调方法里,不要调用阻塞式操作(比如Thread.sleep()、同步数据库查询),否则会占用处理回调的线程,违背非阻塞的初衷。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:09:04