反应式编程(二)Mono<T>、Flux<T> 方法大全

Mono<T>Flux<T> 是 ReactiveX for Java(RxJava)和 Project Reactor(Reactor)这两个响应式编程库中的核心抽象类型,尤其是在 Spring WebFlux 中得到广泛应用。

一、Mono 的常用方法

Mono<T>: 表示包含 0个或1个 元素的 异步序列。它用于表示将来某个时刻可能会产生单个值(也可能会产生空值)的异步操作结果。

1)创建 Mono:

  • Mono.just(T value):创建一个包含单个给定值的 Mono,创建出来的 Mono 序列在发布这些元素之后会自动结束。
  • Mono.empty():创建一个不包含元素,只发布结束消息的 Mono。(在响应式编程中,流的传递是基于元素的,empty 表示没有元素,所以不会进行后续传递,需要使用 switchIfEmpty 进行处理。)
  • Mono.never():empty 里面至少还有一个结束消息,而 never 则是真的啥都没有。
  • Mono.error(Throwable error):创建一个包含给定错误的 Mono。
  • Mono.defer(Callable<Mono<T>> supplier):延迟 Mono 的创建直到订阅时,此时 supplier 函数会被调用实际创建 Mono。示例如下:
Mono.defer(() -> {
    return Mono.error(new RuntimeException);
}).subscribe();
  • Mono.fromCallable(Callable<T> callable):类似于 defer(),但它接受 Callable 并在订阅时执行,返回一个单一结果。使用示例:
Mono.fromCallable(() -> "9999").subscribe(System.out::println);
  • Mono.fromCompletionStage(CompletionStage<T> completionStage):从 CompletionStage 创建 Flux。
  • Mono.fromFuture(CompletableFuture<T> future):从 Future 创建 Flux。
  • Mono.fromRunnable(Runnable runnable):从 Runnable 创建 Flux。
  • Mono.fromSupplier(Supplier<T> supplier):从 Supplier 创建 Flux。
  • Mono.justOrEmpty(Optional<? extends T> data):从一个 Optional 对象中创建 Mono。只有 Optional 对象中包含值时,Mono 序列才产生对应的元素。
  • Mono.justOrEmpty(T data):从一个 可能为 null 的对象中创建 Mono。只有对象不为 null 时,Mono 序列才产生对应的元素。
  • Mono.create(Supplier<MonoSink<T>> sinkSupplier):用于手动控制 Mono 流程,通过 MonoSink 提供数据、完成、或抛出错误的能力。使用示例:
Mono.fromSupplier(() -> "Hello").subscribe(System.out::println);
Mono.justOrEmpty(Optional.of("Hello")).subscribe(System.out::println);
Mono.create(sink -> sink.success("Hello")).subscribe(System.out::println);
  • Mono.delay(Deration duration):创建一个 Mono 序列,在指定的延迟时间之后,产生数字 0 作为唯一值。
  • Mono.delayMillis(long duration):同上,指定具体的毫秒数作为延迟时间。

2)转换和组合:

  • map(Function<T, R> mappper):应用于 Mono 中的数据并映射为新类型。
  • flatMap(Function<T, Mono<R>> mapper):将 Mono 中的值转换为另一个 Mono,并扁平化结果。
  • then(Mono<T> other):当 Mono 完成(成功或失败)时,继续订阅另一个 Mono。
  • zipWith(Mono<?> otherMono, BiFunction<? super T, ?, U> zipper):将两个 Mono 结合在一起,使用 zip 函数合并结果。使用示例:
// 直接拼接 -> [a, c] [b, d]
Flux.just("a", "b")
    .zipWith(Flux.just("c", "d"))
    .subscribe(System.out::println);
// 按照制定规则拼接 -> a-c b-d
Flux.just("a", "b")
    .zipWith(Flux.just("c", "d"), (s1, s2) -> String.format("%s-%s", s1, s2))
    .subscribe(System.out::println);
  • Mono.zip(...Mono sources):合并多个 Mono,当所有 Mono 完成后聚合它们的结果。

3)订阅和消费:

  • subscribe(Consumer<? super T> consumer):订阅 Mono 并在接收到值时执行 Consumer。
  • subscribe(Consumer<? super T> successHandler, Consumer<Throwable> errorHandler):添加成功和错误处理器。
  • block():阻塞等待 Mono 完成并返回结果。(注意:在异步非阻塞环境下慎用)
  • blockFirst():阻塞调用线程,直到发射出的第一个元素到达,返回返回该元素。如果没有元素发射,则会抛出 NoSuchElementException。(当用于 Mono 上时,效果与 block() 相同)
  • blockLast():阻塞调用线程,直到异步序列完成并返回最后一个元素。如果没有元素发射,则会抛出 NoSuchElementException。(当用于 Mono 上时,效果与 block() 相同)

注意:

  • 在 Project Reactor 中,block()blockFirst()blockLast() 这些方法在阻塞期间会 持有主线程,可能导致 线程饥饿响应延迟 等问题,特别是在处理大量数据或长时间运行的任务时。在大部分情况下,尽量避免在生产环境中使用这些方法,因为它们会破坏反应式编程的优势——非阻塞性背压 支持。在响应式编程中,通常建议使用 subscribe() 方法注册回调函数以非阻塞方式处理异步结果。然而,在测试、初始化或者其他特殊情况中,有时确实需要获取一个同步的结果。

二、Flux 的常用方法

Flux<T>: 表示包含 0个或多个 元素的 异步序列。它用于处理连续的数据流,例如集合、数组或事件流。

1)创建 Flux:

  • Flux.just(T... values):创建一个包含一组值的 Flux,创建出来的 Flux 序列在发布这些元素之后会自动结束。
  • Flux.fromArray(T[] array):从数组创建 Flux。
  • Flux.fromIterable(Iterable<T> iterable):从 Iterable 对象创建 Flux。
  • Flux.fromStream(Stream<T> strean):从 Stream 对象创建 Flux。
  • Flux.empty():创建一个不包含任何元素,只发布结束消息的序列。(在响应式编程中,流的传递是基于元素的,empty 表示没有元素,所以不会进行后续传递,需要使用 switchIfEmpty 进行处理。)
  • Flux.never():创建一个不包含任何元素的序列。
  • Flux.error(Throwable error):创建一个只包含错误消息的序列。
  • Flux.range(int start, int count):创建一个包含从 start 开始计数的 count 个整数的 Flux。使用示例:
Flux.range(1, 10)
    .timeout(Flux.never(), v -> Flux.never()) // 表示永不超时
    .subscribe(System.out::println);
  • Flux.interval(Duration period, Duration delay):创建一个按照固定时间间隔不断产生 Long 类型数值的 Flux 序列。这个序列可以用来做定时任务或者周期性触发某些操作。使用示例:

2)转换和过滤:

  • map(Function<T, R> mapper):映射每个元素到新的类型。
  • filter(Predicate<T> predicate):根据给定谓词过滤元素。
  • flatMap(Function<T, Publisher<R>> mapper):将每个元素转换为 Publisher 并扁平化结果。
  • concatMap(Function<T, Publisher<R>> mapper):与 flatMap 类似,但保持顺序输出。

3)控制流:

  • limitRate(int maxConcurrency):限制并发订阅的数量。
  • take(int n):仅取前 n 个元素。
  • skip(int n):跳过前 n 个元素。
  • buffer(int size):按指定大小

4)错误处理与完成:

  • onErrorResume(BiFunction<Throwable, ? super Flux<T>, ? extends Publisher<U>> resumeFunction):当 Flux 发生错误时,提供备用 Publisher 继续发射元素。
  • doOnError(Consumer<Throwable> errorHandler):添加错误处理器。
  • doOnComplete(Runnable onCompleteHook):在 Flux 完成时执行一个钩子方法。

5)订阅和消费:

  • subscribe(Consumer<? super T> consumer):订阅 Flux 并在接收到每个元素时执行 Consumer。
  • subscribe(Consumer<? super T> onNext, Consumer<Throwable> onError, Runnable onComplete):添加完整订阅处理器,包括正常接收、错误处理和完成时的回调。
  • block():阻塞等待 Flux 完成并返回结果。(注意:在异步非阻塞环境下慎用)
  • blockFirst():阻塞调用线程,直到发射出的第一个元素到达,返回返回该元素。如果没有元素发射,则会抛出 NoSuchElementException。
  • blockLast():阻塞调用线程,直到异步序列完成并返回最后一个元素。如果没有元素发射,则会抛出 NoSuchElementException。

注意:

  • 在 Project Reactor 中,block()blockFirst()blockLast() 这些方法在阻塞期间会 持有主线程,可能导致 线程饥饿响应延迟 等问题,特别是在处理大量数据或长时间运行的任务时。在大部分情况下,尽量避免在生产环境中使用这些方法,因为它们会破坏反应式编程的优势——非阻塞性背压 支持。在响应式编程中,通常建议使用 subscribe() 方法注册回调函数以非阻塞方式处理异步结果。然而,在测试、初始化或者其他特殊情况中,有时确实需要获取一个同步的结果。

6)组合和订阅:

  • mergeWith(Flux<? extends T> other):合并两个 Flux 流。
  • reduce(BiFunction<T, T, T> accumulator):对整个序列应用一个累加器函数,返回单一结果。

整理完毕,完结撒花~🌻





参考地址:

1.Mono和Flux的用法详解,https://blog.csdn.net/lz710117239/article/details/93777692

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不愿放下技术的小赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值