Reputation: 422
I understand that a lot of reactor operators like flatMap() run on the same thread on which the onNext method was invoked. What I am trying to understand is if such a method is any more efficient/performant non-blocking than a regular blocking call in say a for loop. Sorry if it's a noob question but I can't seem to grasp it. Is the power of reactive realized only when we use Schedulers that jump threads (e.g. Schedulers.parallel()) and so on?
e.g. if I had a function like the following
List<Integer> integers = Arrays.asList(5,6,7,8,9,10);
Flux.fromIterable(integers)
.flatMap(this::makeAReactiveMethodCall)
.subscribe(r -> log.info(Thread.currentThread().getName()));
Logs look something like this - notice all the threads are the same "main" one.
01:25:40.641 INFO ReactiveTest - main
01:25:40.642 INFO ReactiveTest - main
01:25:40.642 INFO ReactiveTest - main
01:25:40.642 INFO ReactiveTest - main
01:25:40.642 INFO ReactiveTest - main
01:25:40.642 INFO ReactiveTest - main
All invocations happen on the same main thread. How is this code more efficient than making all the call in a for loop with blocking semantics? Say the following code?
integers.forEach(i -> this.makeAReactiveMethodCall(i).block());
Upvotes: 0
Views: 1030
Reputation: 6255
Assuming each makeAReactiveMethodCall
does some I/O and takes 1 second to complete. Using the flatMap
operator your calls will be made asynchronously. This means that the main thread will make all 6 calls without waiting for the I/O operation to complete(non-blocking), instead, it will process some other work and will be notified when a call is completed. In the case of WebClient
and Project Reactor, this is achieved by using the Netty event loop to queue/dispatch/process events.
In the traditional, blocking way(eg. RestTemplate
), it would take 6 seconds to make all 6 calls synchronously. Of course, you could use ExecutorService
API to make it asynchronously, but in that case, you would need 6 threads because calls would be blocking. One of the advantages of the reactive model is that number of threads is limited, thus, resources are not wasted in multiple thread creation.
Upvotes: 2
Reputation: 28301
it's not if makeReactiveMethodCall()
is doing CPU-bound work, or if it is not really reactive at all but a blocking call in disguise.
it's more efficient the moment makeReactiveMethodCall
introduces some latency, eg. by performing I/O in a reactive manner.
there is also a tradeoff in composition and using a unified abstraction for your various processing steps that you might want to consider.
but if you're after pure throughput of CPU-bound code, then by all means use a good old loop.
Upvotes: 1