1 minute
We are all aware of the rise of asynchronous and reactive programing paradigms. Java has already started catching up with other newer languages like Java Script, Go, Python,… that supports this natively. Starting with Java 9 there is possibility support for Reactive Streams. Unfortunately the shift with Java is always slower than expected.
On the quest to optimize my Java code and to start writing reactive/async code I started looking in to the Eclipse Vert.x. This is an opensource extension for Java that delivers async mechanisms as well as providing bunch of other tools needed for running the whole asynchronous ecosystem as well as focusing on microservice/cloud paradigm. On top of that there is a native support for JavaRx APIs that many of you are already familiar with.
The sentence that stuck in my head:
If you have 3 request, the sync model guaranties to deliver the first response faster than the async model but on the other hand async guaranties to deliver response to all 3 in total faster.
Unlike in synchronous programing where requests are processed/handled one by one in order asynchronous model receives a request, generates a call back for it, starts processing it but is free to receive another request. So when another request comes it again generates the callback and so on… When the task is done the callback is called the result of request can be sent. I am referring to request as an action/process/operation,… This saves a lot of time that is wasted on waiting for the request to complete in synchronous programming.
To demonstrate this I have created a simple example where I compare the execution of 5 HTTP GET requests to famous websites.
In the first example I will be using standard java synchronous model. To ease the syntax I am using OkHttp Client which proved itself as very fast and easy HTTP client for Java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import okhttp3.OkHttpClient; import okhttp3.Request; import java.io.IOException; import java.util.Arrays; import java.util.List; public class SyncExample { private static final OkHttpClient client = new OkHttpClient(); public static void main(String[] args) { List<String> urls = Arrays.asList("https://www.google.com/", "https://www.github.com/", "https://www.facebook.com", "https://twitter.com/", "https://www.ipification.com/"); long time = System.currentTimeMillis(); for(String url : urls) { run(url); } System.out.println("Complete in " + (System.currentTimeMillis() - time)); } private static void run(String url) { Request request = new Request.Builder() .url(url) .build(); try { client.newCall(request).execute(); } catch (IOException ex) { System.out.println("Error sending request to url " + url); } } } |
As stated above for async example I will be using Eclipse Vertx. The syntax is a little strange if you haven’t been programing with reactive streams, Futures, Java Rx but for this example there is nothing fancy or hard.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
import io.vertx.core.AbstractVerticle; import io.vertx.core.CompositeFuture; import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.ext.web.client.HttpResponse; import io.vertx.ext.web.client.WebClient; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class AsyncExample extends AbstractVerticle { static Future<Void> completer = Future.future(); public static void main(String[] args) { Vertx vertx = Vertx.vertx(); vertx.deployVerticle(new AsyncExample()); completer.setHandler(x -> System.exit(0)); } @Override public void start() throws Exception { super.start(); WebClient webClient = WebClient.create(vertx); List<String> urls = Arrays.asList("https://www.google.com/", "https://www.github.com/", "https://www.facebook.com", "https://twitter.com/", "https://www.ipification.com/"); List<Future> futures = new ArrayList<>(); urls.forEach(url -> { Future<HttpResponse<Buffer>> future = Future.future(); webClient.getAbs(url).send(future.completer()); futures.add(future); }); long time = System.currentTimeMillis(); CompositeFuture.all(futures).setHandler(x -> { if(x.succeeded()) { System.out.println("Complete in " + (System.currentTimeMillis() - time)); } else { System.out.println("Failed with error = " + x.cause().getMessage()); } completer.complete(); }); } } |
After running both of these examples multiples times and timing all of the runs here are the numbers:
Run #id | SyncExample | AsyncExample |
Run 1 | 3896 ms | 1638 ms |
Run 2 | 3846 ms | 1750 ms |
Run 3 | 4352 ms | 1774 ms |
Average | 4031.33 ms | 1720.66 ms |
Summary
I hope these numbers and the pure idea behind async programing have inspired you to dig deeper in to this paradigm. There are a lot of tools and services which provide these capabilities.
For the end I will leave you with some documentation and tutorials you can follow up. Enjoy!!!
http://reactivex.io/intro.html
https://projectreactor.io/docs
Post A Reply