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
相关产品推荐
相关产品推荐

