为何无法在@RunOnVirtualThread方法中await Mutiny Uni?
为何添加@Blocking注解仍无法在虚拟线程中等待Uni执行完成?
假设系统某部分采用Mutiny实现响应式代码,现需用虚拟线程(Virtual Threads)进行命令式编程,打通两种编程模型,写出了如下代码:
@Blocking @RunOnVirtualThread public SomeItem runOnVirtualThreadAndWaitUni(){ var someItem = doHeavyWorkWithUniResponse().await().indefinitely(); return someItem; }
运行后抛出异常:
java.lang.IllegalStateException: The current thread cannot be blocked: vert.x-eventloop-thread-3
问题原因
核心问题在于注解的执行优先级和Mutiny的线程安全校验逻辑:
- 在Quarkus等常用框架中,
@Blocking的拦截逻辑执行优先级高于@RunOnVirtualThread,导致方法实际先被调度到Vert.x的EventLoop/Worker线程上运行,而非虚拟线程。 - Mutiny的
await().indefinitely()方法会严格校验当前线程类型:如果是Vert.x的EventLoop线程(这类线程是事件驱动模型的核心,必须保持非阻塞),就会直接抛出异常,防止阻塞事件循环拖垮整个系统。
解决方案
直接移除@Blocking注解,仅保留@RunOnVirtualThread即可:
@RunOnVirtualThread public SomeItem runOnVirtualThreadAndWaitUni(){ var someItem = doHeavyWorkWithUniResponse().await().indefinitely(); return someItem; }
补充说明
@RunOnVirtualThread本身已经包含了"允许阻塞操作"的语义——虚拟线程是轻量级线程,阻塞虚拟线程只会挂起当前虚拟线程实例,不会占用底层的平台线程(比如Vert.x的EventLoop线程),完全符合Mutiny对阻塞操作的线程安全要求。而@Blocking是为传统平台线程设计的阻塞标记,和虚拟线程的调度逻辑冲突,叠加使用反而会导致线程调度异常。
内容的提问来源于stack exchange,提问作者Marian Klühspies
相关产品推荐
相关产品推荐

