跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Reactor 中模拟非阻塞延迟的正确实践

在 spring react or 中,需避免 `thread.sleep()` 等阻塞调用;应使用 `mono.delay()`、`flux.delayelements()` 等响应式原语,在不占用线程、不触发线程切换(或可控切换)的前提下,真实模拟耗时但非阻塞的操作。 在 响应式编程 中,“模拟长时间运行操作”常被误解为“让当前线程休眠”。但 Thread.sleep() 是典型的 阻塞式 I/O 风格操作 ——它会挂起当前线程,导致资源浪费、吞吐下降,并被 BlockHound 明确标记为非法。真正的非阻塞延迟,本质是: 将任务调度到未来某个时间点执行,期间线程立即释放,用于处理其他信号 。 ✅ 正确方式:用 Mono.delay() 构建非阻塞耗时逻辑 Mono.delay(Duration) 返回一个在指定延迟后发出 0L 的 Mono,它底层基于 ScheduledExecutorService(默认使用 Schedulers.parallel()), 不阻塞任何线程 ,仅注册一个定时任务。你可以将其作为“时间占位符”,再通过 map 或 flatMap 衔接实际业务逻辑:
public Mono simulateLengthyProcessingOperation(Integer input) { return Mono.delay(Duration.ofSeconds(4)) // 非阻塞等待 4 秒(调度+唤醒) .map(unused -> String.format( "[%d] on thread [%s] at time [%s]", input, Thread.currentThread().getName(), new Date() )); }
⚠️ 注意:Mono.delay() 默认在 Schedulers.parallel() 上执行,因此后续 map 中的代码也运行在该线程池中——这正是响应式“线程解耦”的体现,而非“同一线程上忙等”。 ? 整合进数据流:使用 concatMap 保持顺序 + 非阻塞延迟 回到原始测试用例,若需对每个整数 1..5000 执行带延迟的处理(且要求顺序输出、不并发),应避免 map(它是同步、无调度能力的),改用 concatMap:
@Test public void simulateLengthyProcessingOperationReactor() { Flux.range(1, 5000) .concatMap(this::simulateLengthyProcessingOperation) // 逐个订阅,顺序执行 .subscribe( System.out::println, Throwable::printStackTrace, () -> System.out.println("✅ All done!") ); }
concatMap 保证前一个 Mono 完成后才订阅下一个,天然串行化,同时全程无阻塞、无线程抢占——完美契合“模拟长耗时但非阻塞”的需求。 React Native For Android 源码编译 中文WORD版 本文档主要讲述的是React Native For Android 源码编译;希望对大家会有帮助;感兴趣的朋友可以过来看看 下载 ❌ 常见误区澄清 Flux.delayElements() 是对 元素发射节奏 做延迟(如每秒发一个),不适用于“每个元素内部执行耗时逻辑”; Thread.sleep() 在任何 map/filter 中都是反模式,BlockHound 会抛出 BlockingOperationException; Mono.fromCallable(() -> { Thread.sleep(...); return ...; }) 仍是阻塞的——它只是把阻塞操作包装进 Mono,并未消除阻塞本质。 ✅ 进阶建议:显式控制调度器(可选) 如需指定延迟执行的线程池(例如避免干扰 parallel() 默认调度器),可显式传入 Scheduler:
Mono.delay(Duration.ofSeconds(4), Schedulers.boundedElastic()) .map(...);
boundedElastic() 更适合模拟 I/O 延迟(如数据库响应),而 parallel() 更适合 CPU 密集型延时调度。 总结 非阻塞延迟 ≠ 让线程睡觉,而是 委托给事件循环/调度器在未来唤醒任务 。Reactors 提供的 Mono.delay() 和 Flux.delayElements() 正是为此设计。在模拟耗时业务逻辑时,始终优先选择 Mono.delay().flatMap(...) 或 concatMap 组合,既满足 BlockHound 合规性,又保持高吞吐与低资源开销。

相关文章