如何用repeatWhen和takeUntil实现Mono定时重复订阅直至满足条件?
问题分析与修复
你的代码只打印一次UUID就退出的核心原因是:Mono.just(UUID.randomUUID())在创建Mono实例时就已经生成了唯一的UUID,后续通过repeatWhen重复订阅时,只会返回这个预先生成的固定值——如果这个UUID不以"1234"开头,takeUntil永远不会触发终止条件,但主线程会在订阅后直接退出,导致程序结束;如果恰好第一个UUID符合条件,就会打印一次后停止。
修复后的代码
要实现每次重复时生成新的UUID,需要改用Mono.fromSupplier,它会在每次订阅时执行传入的供应商函数,生成新的随机UUID:
import java.util.UUID; import reactor.core.publisher.Mono; import java.time.Duration; public class UuidGenerator { public static void main(String[] args) { Mono.fromSupplier(() -> UUID.randomUUID()) .map(UUID::toString) .doOnNext(System.out::println) .repeatWhen(completed -> completed.delayElements(Duration.ofMillis(1000))) .takeUntil(uuid -> uuid.startsWith("1234")) .subscribe(); // 如果是在main方法中运行,需要阻塞主线程防止程序立即退出 try { Thread.currentThread().join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }
关键修改说明
- 替换
Mono.just为Mono.fromSupplier:fromSupplier的lambda表达式会在每次订阅(包括重复订阅)时执行,保证每次都生成全新的UUID。 - 主线程阻塞处理:如果是在独立的main方法中运行,订阅后主线程会立即结束,导致Reactor的异步任务也随之终止。通过
Thread.currentThread().join()可以让主线程保持存活,直到生成符合条件的UUID。
内容的提问来源于stack exchange,提问作者Melad Basilius
相关产品推荐
相关产品推荐

