Reactive Programming in Java: How, Why, and Is It Worth Doing? Examples of Parallel and Asynchronous Approaches
Let’s review two options of thread execution: parallel and asynchronous.
Threads are executed in parallel
Thread 1 and thread 2 need to address the same shared resource. Suppose it’s some database, which doesn't allow the threads to connect to it simultaneously. Or it does, but this immediately decreases its speed, and therefore the thread should better address the DB in turns. There is no parallelism here: the threads have to take turns. The third thread is waiting for a response from the database and is blocked too – this is ineffective.
There seems to be a kind of parallelism, yet it provides little benefits.
Threads are running asynchronously
If they are asynchronous, we set a task, and it is executed in some other thread, for example, by another processor core or another CPU. We have set a task and continue doing other things, and at a particular moment later on, once the task is completed, we’ll get the results. The work within an organization can illustrate this. The manager (main thread) is assigning a task to Pete and says: “Once you finish it, pass it to Nick, and when he completes the task, he should report to me.” Pete and Nick are busy with the task, and the manager can assign new tasks to other employees.
Another example: concurrency and parallelism.
Imagine a morning in the office, everybody eager to get a cup of coffee. Concurrency – is when a queue is lining up for the single coffee machine. People are competing: “Hey, I'm the first here!” “Nope, it’s me!” They impede each other.
In the case of parallelism, there are two coffee machines and two queues – everyone is lining in their queue. Nevertheless, employees are wasting time in the queue.
What would be the right solution for this case if we make it asynchronous?
Delivering coffee to each desk is a good option – people don't have to queue, but you’ll have to hire a waiter to serve drinks.
Another option is a fixed schedule. For instance, one employee comes for coffee at 11:11, the next at 11:20, and so on. But this is not an asynchronous process. There could be downtimes, which means the coffee machine will not be fully loaded. Someone might be late, or for somebody, it takes more than 10 minutes to make coffee, and the schedule is shifting.
And if you make the intervals longer, the coffee machine will be underloaded. Besides, everyone wants to have a cup of coffee at 10 in the morning, without waiting 2 hours to get their coffee only at 12.
Another option is to make a “virtual queue” for everyone. When the coffee machine is free, a person gets a notice and gets to the machine without waiting in line. They do it like that in many organizations nowadays, for example, in online shops offering local pickup. You get notice and continue doing your chores, and when your time comes, you pick up your purchase.
This is an asynchronous process: nobody is waiting for anyone; everybody continues working and gets their coffee as soon as possible. And the coffee machine is not standing idle.
So much for async. Yet there is another important problem – blocking I/O.