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

Java响应式编程中对象转Mono及实现异步执行避免主线程阻塞的问题

Java响应式编程中对象转Mono及实现异步执行避免主线程阻塞的问题

兄弟,你遇到的问题其实是没搞懂Reactor中Mono创建的时机和线程调度逻辑~ 咱们先拆解下你原有代码阻塞主线程的原因:

你用了Mono.just(getValue()),这里的getValue()是在创建Mono的瞬间就同步执行了,而不是等到订阅时才触发。所以主线程在调用Mono.just()的那一刻,直接就进入了Thread.sleep(10000),自然会被卡住10秒,完全没达到异步的效果。

要实现你想要的「主线程不等待Mono执行完成,直接结束」的目标,需要做两个关键调整:

  • 用延迟执行的方式创建Mono,让getValue()的调用推迟到订阅阶段,而非Mono创建阶段
  • 指定异步调度器,让getValue()在单独的线程中运行,不占用主线程资源

修改后的代码示例(含结果验证)

如果想看到异步任务的输出结果,需要让主线程短暂存活(否则JVM会直接退出,异步线程来不及执行):

public static void main(String[] args) {
    // 用fromSupplier延迟执行getValue,并用subscribeOn指定异步线程池
    Mono.fromSupplier(() -> getValue())
        .subscribeOn(Schedulers.boundedElastic())
        .subscribe(value -> System.out.println("异步任务输出:" + value));

    // 主线程继续执行自身逻辑
    System.out.println("主线程执行完成,准备退出...");

    // 可选:让主线程短暂停留,确保异步任务能执行完毕并输出结果
    try {
        Thread.sleep(11000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

public static int getValue() {
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    return 10;
}

如果你的需求是主线程完全不等待,直接终止(此时异步任务可能来不及执行就被JVM终止),只需去掉最后的Thread.sleep(11000)即可——主线程会直接打印日志后退出,完全不会被异步任务阻塞。

额外知识点补充

  • Mono.fromSupplier():接收一个Supplier接口,只有当Mono被订阅时才会调用Supplier的get()方法,实现了真正的延迟执行
  • subscribeOn(Schedulers.boundedElastic()):指定Mono的执行逻辑在boundedElastic线程池中运行,这个线程池专门用于处理阻塞性IO或长时间运行的任务,不会占用主线程
  • 若需要处理checked异常,也可以用Mono.fromCallable(),它和fromSupplier逻辑类似,但允许抛出checked exception

备注:内容来源于stack exchange,提问作者Prasad Selenium

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:33:08