Probably you also had a difficult start concerning RxJava and threading like Graham Lea did.
I had.
Why did I? I made some false assumptions regarding threading instead of properly learning "stuff" first using e.g. http://www.pluralsight.com/courses/reactive-programming-java-8-rxjava.
The main point about Rx and parallelsim / concurrency is probably noted here http://www.introtorx.com/Content/v1.0.10621.0 and states
a) "Rx is single-threaded by default"
and
b) "While Rx has concurrency features, these should not be mistaken for a concurrency framework. Rx is designed for querying data, and as discussed in the first chapter, parallel computations or composition of asynchronous methods is more appropriate for other frameworks."
Rx is created mainly for "clients" (client applications like apps, desktop gui applications, …) where you have typically one thread from the GUI and you would like to "spin off" several background tasks (in parallel).
Rx is excellent at that, at doing different things in parallel and combining the asynchronous returning results.
When it comes to doing same things in parallel, like in a server where you handle hundreds of client calls in parallel, then Rx is not that straight forward. You start with creating Observables, using subscribeOn and flatMap, just to get same things to run in parallel. Here are some examples for this.
Think of a McDrive with one lane and very few customers arriving. The one lane is either free or there is one customer. Each customer orders always the same three "things", which you can prepare with 3 workers in the background "in parallel".
-
Parallelism in a sense of different things in parallel: We can do three things in parallel for one customer
-
Based on the flatmap operator
In this example there is no need for backpressure, since the customers arrive "slow " and the McDrive can handle them in time.
But what happens if you increase the number of arriving customers (=switch from seconds in arrivals interval operator to milliseconds)?
As expected, you get a MissingBackpressureException.
An Implementation of OneLaneMcDrive without the flatmap operator. Instead we use a PublishSubject instance to "communicate the result to the outside" and use an AtomicBoolean instance to limit the number of concurrent customers to one.
You immediately understand now the "power" of the flatmap operator.
Same as OneLaneMcDrive, but now with two lanes. There are still few customers arriving concurrently. Each of the lane is either free or there is maximum one customer in the lane. We have at each time between 0 and 2 customers concurrently.
-
Parallelism in a sense of same things in parallel: We can handle two customers at the same time
-
Parallelism in a sense of different things in parallel: like OneLaneMcDrive
There is also no need for backpressure, since the customers arrive "slow " and the McDrive can handle them in time.
Same as OneLaneMcDrive, but now with more customers arriving. The McDrive can’t handle all of them "just in time", so a wait line (queue) builds up. The longer the example runs, the longer the wait line becomes.
We need some kind of backpressure: we choose buffering (queueing) and get a "jam" (queue becomes longer and longer).
Now, we have an "infinite" number of lanes. The number of lanes grows to the point when we have enough lanes to handle all the arriving customers "just in time".
We output the numer of lanes (=number of concurrently handled customers).
Let’s come back from the food to the technical details.
As initially said, RxJava is "single threaded by default". Although you can offload the work from one thread to an other (using Schedulers), the program flow then is switching from one thread to another one thread and not to a pool of threads. Your sourcecode (e.g. your observer) is always called by only one (and usually the same) thread.
Benefit? You don’t have to implement thread-safe code, which is hard.
Drawback? There might be a lot of threads just sitting around. Since a thread is currently (Java 8) a heavy resource, this is suboptimal. A possible solution: Rewrite RxJava to use fibers (lightweight threads).