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

Quarkus Mutiny中Uni/Multi如何等待请求响应完成?

Quarkus Mutiny异步操作正确实现方案(解决提前返回空结果/EventLoop阻塞问题)

场景一:延迟处理列表元素并返回完整结果

问题根源

原代码在forEach里创建Uni后直接调用subscribe(),异步操作会在后台执行,但主线程会立刻返回空的finalList——此时异步延迟还没结束,元素根本没来得及添加。Mutiny的异步逻辑必须通过链式调用串联,不能手动订阅后直接返回未完成的结果。

修正后的代码

@GET
@Path("/testingAsync")
public Uni<List<String>> testingMutiny() {
    List<String> completeList = Arrays.asList("hello", "RestEasy");

    // 将列表转为流式异步处理,等待全部元素完成后返回
    return Multi.createFrom().iterable(completeList)
            .onItem().transform(item -> item.toUpperCase())
            .onItem().delayIt().by(Duration.ofMillis(10000))
            .collect().asList();
}

说明

  • 用Multi.createFrom().iterable()把列表转为异步流,逐个处理元素
  • 先完成转大写操作,再添加延迟逻辑
  • 最后通过collect().asList()等待所有元素处理完毕,返回包含完整结果的Uni<List<String>>

场景二:并行调用多个外部接口更新Car对象并返回完整结果

问题根源

原代码调用Uni.combine()后直接subscribe(),更新Car的异步逻辑在后台跑,但主线程立刻返回了未更新的Car对象。另外遍历多个Car时,必须把每个Car对应的异步操作收集起来,等全部完成后再返回列表。

修正后的代码

假设你有初始的Car列表需要处理:

@GET
@Path("/testingAsync")
public Uni<List<Car>> testingMutiny() {
    List<Car> initialCars = getInitialCars(); // 替换为你的初始Car列表获取逻辑

    // 遍历每个Car,生成对应的异步处理Uni,最后收集所有结果
    return Multi.createFrom().iterable(initialCars)
            .onItem().transformToUni(car -> {
                // 并行发起三个外部接口请求
                Uni<List<JsonObjectCar>> carDoorsUni = getDoors(variable1, variable2, variable3);
                Uni<List<JsonObjectCar>> carWheelsUni = getWheels(variable1, variable2, variable3);
                Uni<List<JsonObjectCar>> carWindowsUni = getWindows(variable1, variable2, variable3);

                // 组合三个Uni,等待全部完成后更新Car
                return Uni.combine().all().unis(carDoorsUni, carWheelsUni, carWindowsUni)
                        .combinedWith((carDoors, carWheels, carWindows) -> {
                            Optional.ofNullable(carDoors)
                                    .ifPresent(val -> car.setDoors(val.getDoors()));
                            Optional.ofNullable(carWheels)
                                    .ifPresent(val -> car.setWheels(val.getWheels()));
                            Optional.ofNullable(carWindows)
                                    .ifPresent(val -> car.setWindows(val.getWindows()));
                            return car;
                        })
                        // 设置超时,超时直接抛出异常,避免返回不完整结果
                        .ifNoItem().after(Duration.ofSeconds(30)).fail();
            })
            .collect().asList();
}

说明

  • 用Multi遍历初始Car列表,每个Car对应一个独立的异步处理Uni
  • Uni.combine().all().unis()并行执行三个外部请求,等全部返回后再更新Car对象
  • 通过ifNoItem().after().fail()设置超时,超时直接报错,不会返回未完成的Car
  • 最后用collect().asList()等待所有Car处理完成,返回完整结果列表

关键注意事项:避免EventLoop线程阻塞

你遇到的The current thread cannot be blocked: vert.x-eventloop-thread-14错误,核心原因是Quarkus基于Vert.x的EventLoop线程是非阻塞线程,绝对不能调用await()这类阻塞方法。正确的做法是:

  • 所有异步逻辑都封装在Uni/Multi中,通过Mutiny的链式API(transformToUni、combine、collect等)串联
  • 由Mutiny自动管理线程和异步流程,不要手动阻塞等待
  • 超时控制用Mutiny提供的ifNoItem()系列API,而非手动阻塞

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 19:05:29