Why does Thread.sleep() trigger the subscription to Flux.interval()?

一个人想着一个人 提交于 2020-06-27 16:59:08

问题


If, in a main() method, I execute this

Flux.just(1,2)
    .log()
    .subscribe();

I get this in the console:

[ INFO] (main) | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription)
[ INFO] (main) | request(unbounded)
[ INFO] (main) | onNext(1)
[ INFO] (main) | onNext(2)
[ INFO] (main) | onComplete()

If instead of just() I use the interval() method:

Flux.interval(Duration.ofMillis(100))
    .take(2)
    .log()
    .subscribe();

the elements are not logged, unless I add Thread.sleep() which gives me:

[ INFO] (main) onSubscribe(FluxTake.TakeSubscriber)
[ INFO] (main) request(unbounded)
[ INFO] (parallel-1) onNext(0)
[ INFO] (parallel-1) onNext(1)
[ INFO] (parallel-1) onComplete()

The question is: why do I require to pause a thread to actually trigger the subscription ?


回答1:


You need to wait on main thread and let the execution complete. Your main thread terminates before next element is generated. Your first element is generated after 100 ms so you need to wait/block the main thread. Try this:

CountDownLatch latch = new CountDownLatch(1);
Flux.interval(Duration.ofMillis(100))
        .take(2)
        .doOnComplete(latch::countDown)
        .log()
        .subscribe();
latch.await(); // wait for doOnComplete

CountDownLatch:

A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.




回答2:


Flux.interval(Duration) produces a Flux that is infinite and emits regular ticks from a clock.

So your first example has no concurrency, everything happens on the same thread. The subscription and all events must complete before the method and process ends.

By using Flux.interval you have added concurrency and asynchronous behaviour into your example. Interval is a regular clock like a metronome. You subscribe but immediately complete and the process will usually finish before any work (onNext) is done.




回答3:


Flux.interval(..) emits items on a parallel, freeing up your calling thread. This is why your program exits. What you should do is:

Flux.interval(Duration.of(duration))
    .take(n)
    .doOnNext(this::logElement)
    .blockLast();

This will block the calling thread till doOnNext() emits the last time (which should be the second item form the upstream).



来源:https://stackoverflow.com/questions/61767404/why-does-thread-sleep-trigger-the-subscription-to-flux-interval

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!