Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between block() , subscribe() and subscribe(-)

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

output : 0

Not able to see any output on console when I am calling with subscribe() or subscribe(-) methods instead of block()

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

Do we need to use only doOnSubscribe(-) after this Mono.delay(-) method?

 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);

output it's printing doOnSubscribe

like image 437
G SriHAri Avatar asked Nov 17 '25 02:11

G SriHAri


2 Answers

Your block() call explicitly holds the main thread until the publisher completes. By the time it's completed, it's executed the map() call, therefore printing the value.

Your subscribe() call on the other hand asynchronously executes the Mono on a separate scheduler, leaving your main thread to complete. Since the scheduler used by default uses daemon threads to execute your subscription, your program won't wait for it to complete before terminating.

If you introduce a delay long enough for the Mono to complete, you'll see the result you expect:

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

Thread.currentThread().sleep(500);

0 is then printed twice, once for the map() call and once by the System.out::println being used as a consumer.

In a real world use case you obviously won't just put in arbitrary sleep() calls - a CountDownLatch would be a more sensible choice:

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();
like image 56
Michael Berry Avatar answered Nov 18 '25 20:11

Michael Berry


To add what @MichaelBerry said in his excellent answer, and maybe to make it simpler:

The main difference is that subscribe() just "starts the whole computation" and doesn't wait (by contract) for its result. The computation may run in any other thread or even multiple threads. It may sometimes run only in the calling thread itself, which then looks like the same as block(). However, this is not by contract.

In contrast to block(), which by contract starts the computation and waits until it finishes.

You may also read my description here to understand why sometimes subsribe() and block() might give the same result.

like image 34
Honza Zidek Avatar answered Nov 18 '25 21:11

Honza Zidek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!