We believe in Trust, Quality, Responsblility and Teamwork

Happy Easter!

Warmest wishes for a delightful Easter filled with laughter, love, and the simple joys of springtime. May this season renew your spirit and bring you closer to those you cherish. Happy Easter!

Taming the asynchronous beast Reactive Programming in Java

Reactive Programming provides a development model to tame the asynchronous beast.
But first… what is Reactive Programming and why do we want to use it?

In this article, we start our journey into the Reactive Programming World in Java by presenting motivations for Reactive Programming.

Two ways to improve an application’s performance

Generally, there are 2 ways for improving applications’ performance:

  • use more threads and more hardware resources
  • use each thread more efficiently

Why is multithreading not always efficient?

Usually, Java developers tend to write applications in a blocking way – it is fine until there is a performance bottleneck.
As soon as there is I/O operation (like a network call, or a database request), resources are wasted because threads are in idle state (waiting for data).
Additional threads and more cores can be an easy solution, but it has serious weakness:

  • those additional threads are still running similar blocking code
  • growing cost of infrastructure (more cores)
  • a new threading in java is expensive
  • each thread occupies some space in the RAM (https://www.baeldung.com/jvm-configure-stack-sizes)
  • scaling in resource utilization can introduce contention and concurrency problems

How to use each thread more efficiently?

The key word is: asynchronous.
But first: what is synchronous programming?

Code is run sequentially from the top to the bottom and
Its execution is blocked on various long running IO operations (networking, database).

So what does asynchronous mean?

SynchronousWe know when it will happen.
AsynchronousWe do not know when it will happen.
Author: https://softwareengineering.stackexchange.com/users/6505/eric-lippert
Source: https://softwareengineering.stackexchange.com/a/396590

Asynchronous just means the calling thread doesn’t sit and wait for the response, nor does the asynchronous activity happen in the calling thread.
Author: https://stackoverflow.com/users/5801/michael-kohne
Source: https://stackoverflow.com/questions/600795/asynchronous-vs-multithreading-is-there-a-difference

Whenever the operation that needs to happen asynchronously does not require the CPU to do work, that operation can be done without spawning another thread. For example, if the async operation is I/O, the CPU does not have to wait for the I/O to complete. It just needs to start the operation, and can then move on to other work while the I/O hardware (disk controller, network interface, etc.) does the I/O work. The hardware lets the CPU know when it’s finished by interrupting the CPU, and the OS then delivers the event to your application.
Author: https://stackoverflow.com/users/60191/karunski
Source: https://stackoverflow.com/questions/600795/asynchronous-vs-multithreading-is-there-a-difference

Asynchronicity allows for non-blocking execution but is hard without non-blocking IO.
Note: it does not require a multithreading (even in Java) – thing about callbacks.

Synchronous vs Asynchronous vs Threaded

Let’s make some visualizations.
There are 3 tasks to be done: blue, orange and green.

Obraz zawierający zrzut ekranu, tekst, oprogramowanie, Oprogramowanie multimedialne Opis wygenerowany automatycznie

Figure 1.

On the top, there is the synchronous model.
The first, blue task is started, but there are some IO operations and the thread is waiting for a result of this IO operation. When the blue task is finished, then the orange task can start, and after the orange task completion, the last one (green) can be processed.

Please notice that IO operation can take almost all the time of execution – HTTP requests, fetching from DB, etc … IO operations take the most time of execution.

By writing asynchronous, non-blocking code, you let the execution switch to another active task and later comes back to the current process when the asynchronous IO operation has finished.

There can also be threaded models for both (synchronous and asynchronous).

An execution time for a synchronous threaded model can be widely reduced (in comparison to single-threaded model) BUT resource utilization is growing.

The most efficient approach seems to be an asynchronous threaded model.

Concurrent & Parallel

To complete our handbook, we need to take a look at concurrent vs parallel execution.

Parallel

Obraz zawierający tekst, zrzut ekranu, Czcionka, linia Opis wygenerowany automatycznie

Figure 2.

In parallel executions, tasks are running at the same time on different cores (multiple cores are needed).

Concurrent

Obraz zawierający tekst, zrzut ekranu, Czcionka Opis wygenerowany automatycznie

Figure 3.

In concurrent execution, many tasks are taking a slice of CPU for a small amount of time (it does not require multiple cores). Execution just seems to run simultaneously. Even programs running in single CPU setup can be concurrent.

The essence of differentiation has been great visualized in:

Obraz zawierający tekst, pismo odręczne, diagram, Czcionka Opis wygenerowany automatycznie

Figure 4. (source: https://joearms.github.io/published/2013-04-05-concurrent-and-parallel-programming.html )

How to write asynchronous code on the JVM?

We know right now that asynchronous is awesome and let’s try to use that.
But wait…
How can we produce asynchronous code on the JVM?

Java offers two models of asynchronous programming:

callback-based

  • asynchronous method takes an extra callback parameter(a lambda) that gets called when the result is available

future-based

  • java.util.concurrent.Future
    • Introduced in Java 1.5 (2005)
    • weakness:
      • no notify on completion
      • no chaining
      • no exception handling
  • java.util.concurrent.CompletableFuture
    • Java 8 (2015)
    • Future + missing features

Are the original Java’s techniques good enough?

Not for every use case, both approaches have their own limitations.

Callbacks are hard to compose together, quickly leading to code that is difficult to read and maintain (known as Callback Hell).

Obraz zawierający tekst, zrzut ekranu, Czcionka Opis wygenerowany automatycznie

Figure 5.

And also the (Completable)Future API is quite limited.

Obraz zawierający tekst, zrzut ekranu, Czcionka Opis wygenerowany automatycznie

Figure 6.

Taming the asynchronous beast – Reactive Programming

Let’s try to tame the asynchronous beast…
Here Reactive Programming comes to rescue.

What is Reactive Programming?
Let’s explain in a real-life example:

It’s Friday and John wants to spend this evening with his friend Bob, scarfing pizza and watching one of the Star Wars episodes.

syncJohn finishes his work. Then goes and orders the pizza, waits till it’s done. Then picks up his friend. And finally (with Bob and pizza) makes it home and gets down to the movie.
asyncJohn orders his pizza online, phones Bob, invites him to come. He heads home, has his pizza delivered and starts watching the movie (and eating the pizza) without waiting for Bob to show up.
reactiveJohn orders pizza, phones Bob, invites him to come, heads home, and gets his pizza delivered. But this time, he waits until Bob comes and only after that he turns the movie on.
Source: https://www.scnsoft.com/blog/java-reactive-programming

 

More about Reactive Programming in Java in the upcoming tech-news.