block() 、 subscribe() 和 subscribe(-) 之间有什么区别

G S*_*Ari 18 project-reactor spring-webflux

Mono.delay(Duration.ofMillis(10)).map(d -> {
            System.out.println(d);
            return d;
        }).block();
Run Code Online (Sandbox Code Playgroud)

输出:0

当我使用subscribe()subscribe(-)方法而不是调用时,无法在控制台上看到任何输出block()

Mono.delay(Duration.ofMillis(10)).map(d -> {
        System.out.println(d);
        return d;
    }).subscribe(System.out::println);
Run Code Online (Sandbox Code Playgroud)

doOnSubscribe(-)难道我们只需要在这个方法之后使用吗Mono.delay(-)

 Mono.delay(Duration.ofMillis(10)).doOnSubscribe(s -> {
        System.out.println("its printing doOnSubscribe");
    }).map(d -> {
        System.out.println(d);
        return d;
    }).subscribe(System.out::println);
Run Code Online (Sandbox Code Playgroud)

输出它正在打印doOnSubscribe

Mic*_*rry 31

您的block()调用显式保留主线程,直到发布者完成。当它完成时,它会执行调用map(),从而打印该值。

subscribe()另一方面,您的调用Mono在单独的调度程序上异步执行,让主线程完成。由于默认使用的调度程序使用守护线程来执行您的订阅,因此您的程序不会等待它完成才终止。

如果您引入足够长的延迟来Mono完成,您将看到您期望的结果:

Mono.delay(Duration.ofMillis(10)).map(d -> {
    System.out.println(d);
    return d;
}).subscribe(System.out::println);

Thread.currentThread().sleep(500);
Run Code Online (Sandbox Code Playgroud)

0然后打印两次,一次用于调用map(),一次用于System.out::println作为消费者使用。

在现实世界的用例中,您显然不会只是进行任意sleep()调用 - aCountDownLatch将是一个更明智的选择:

CountDownLatch cdl = new CountDownLatch(1);
Mono.delay(Duration.ofMillis(10))
        .map(d -> {
            System.out.println(d);
            return d;
        })
        .doOnTerminate(() -> cdl.countDown())
        .subscribe(System.out::println);
cdl.await();
Run Code Online (Sandbox Code Playgroud)

  • 在这种情况下,CountDownLatch 解决方案相当于调用一个简单的 `block()`,除了在上面的代码中错误会丢失,除非我们显式指定错误处理程序,在 `block()` 的情况下,错误会自动抛出反应堆。 (4认同)