When executing that code in a main, this is a good demonstration of the asynchronous nature of things. The operation runs on a thread from the elastic scheduler, and subscribe triggers the asynchronous processing so it returns immediately.
There are two ways of synchronizing the end of the application with the end of the Flux
:
print in doOnNext
and use blockLast()
The block* methods are typically used in main and tests, where there is no choice but to switch back to a blocking model (ie because otherwise the test/main would exit before the end of the processing).
We switch the "side effect" of printing each emitted item in a doOnNext
, which is dedicated to that sort of use cases. Then we block up until the completion of the flux, with blockLast()
.
Flux.range(0, 1000000)
.parallel()
.runOn(Schedulers.elastic())
.sequential()
.count()
.doOnNext(System.out::println)
.blockLast();
print in subscribe
and use a CountDownLatch
in doFinally
This one is a bit more convoluted but allows you to actually use subscribe if you want to explore how that method works.
We just add a doFinally
, which triggers on any completion signal (cancellation, error or completion). We use a CountDownLatch
to block the main thread, which will be asynchronously counted down from within the doFinally
.
CountDownLatch latch = new CountDownLatch(1);
Flux.range(0, 1000000)
.parallel()
.runOn(Schedulers.elastic())
.sequential()
.count()
.doFinally(signal -> latch.countDown())
.subscribe(System.out::println);
latch.await(10, TimeUnit.SECONDS);
main
or a unit test, and the JVM exits before the computation terminates (due to running in a separate elastic thread)? – Fettermain
. – Jehoshaphat