{"id":39139,"date":"2015-04-15T22:00:44","date_gmt":"2015-04-15T19:00:44","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=39139"},"modified":"2015-04-13T15:45:32","modified_gmt":"2015-04-13T12:45:32","slug":"farewell-to-asynchronous-code","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html","title":{"rendered":"Farewell to Asynchronous Code"},"content":{"rendered":"<p><a href=\"https:\/\/github.com\/puniverse\/quasar\">Quasar<\/a> is a library that adds true lightweight threads (fibers) to the JVM. These are very cheap and very fast \u2013 in fact, fibers behave just like Erlang processes or Go goroutines \u2013 and allow you to write simple blocking code while enjoying the same performance benefits of complex asynchronous\u00a0code.<\/p>\n<p>In this post we\u2019ll learn how to transform any asynchronous, callback-based API, into a nice (fiber-)blocking API. It is intended for people who wish to integrate their own \u2013 or third-party \u2013 libraries with <a href=\"https:\/\/github.com\/puniverse\/quasar\">Quasar<\/a> fibers. You don\u2019t need to know this stuff if you just use Quasar fibers with channels or actors, or make use of the many integrations already available in the <a href=\"https:\/\/github.com\/puniverse\/comsat\">Comsat<\/a> project (the code presented below is code the application developer never sees). But even if you don\u2019t, you might find this post helpful in understanding how Quasar does its\u00a0magic.<\/p>\n<h2>Why\u00a0Async?<\/h2>\n<p>The reason why many libraries provide asynchronous APIs in the first place, is that the number of running<sup><a name=\"num-threds\">1<\/a><\/sup> threads the OS can handle is far lower than, say, the number of open TCP connections the OS can maintain. Namely, your machine can support much higher concurrency than offered by threads, so libraries \u2013 and the developers using them \u2013 abandon the thread as the abstraction used for a unit of software concurrency <sup><a name=\"littles-law\">2<\/a><\/sup>. Asynchronous APIs don\u2019t block threads and can lead to significant performance gains (usually in throughput and server capacity \u2013 not so much in\u00a0latency).<\/p>\n<p>But using asynchronous APIs also creates code that has rightfully earned the name \u201ccallback hell\u201d. Callback hell is bad enough in environments that lack multi-core processing, like Javascript; it can be a lot worse in those, like the JVM, where you need to care about memory visibility and\u00a0synchronization.<\/p>\n<p>Writing blocking code running on fibers gives you the <a href=\"http:\/\/blog.paralleluniverse.co\/2014\/05\/29\/cascading-failures\/\">same advantages as async code<\/a> without the downsides: you use nice blocking APIs (you can even keep using the existing ones), but you get all the performance benefits of non-blocking\u00a0code.<\/p>\n<p>To be sure, asynchronous APIs have one more advantage: they allow you to dispatch several IO operations (like HTTP requests) concurrently. Because these operations usually take long to complete, and they are often independent, we can simultaneously wait for several of them to complete. This useful features, however, is also possible with Java futures, without requiring callbacks. Later we\u2019ll see how to make fiber-bocking\u00a0futures.<\/p>\n<h2>FiberAsync<\/h2>\n<p>Many modern Java IO\/database libraries\/drivers come with two flavors of APIs: a synchronous (thread-)blocking one, and a callback-based asynchronous one (this is true for NIO, JAX-RS client, Apache HTTP client and many more). The synchronous API is much\u00a0nicer.<\/p>\n<p>Quasar has a programmatic tool that transforms any callback-based asynchronous API into a nice fiber-blocking one: <a href=\"http:\/\/docs.paralleluniverse.co\/quasar\/javadoc\/co\/paralleluniverse\/fibers\/FiberAsync.html\"><code>FiberAsync<\/code><\/a>. Essentially, what <code>FiberASync<\/code> does is block the current fiber, install the async callback, and when the callback is fired, it wakes up the fiber again, and returns the result of the operation (or throws an exception if it\u00a0failed).<\/p>\n<p>To understand how to use <code>FiberAsync<\/code>, we\u2019ll look at an example of an API: <code>FooClient<\/code>. <code>FooClient<\/code> is a modern IO API, so it\u2019s got two flavors, a synchronous, thread blocking one, and an asynchronous one. Here they\u00a0are:<\/p>\n<pre class=\" brush:java\">interface FooClient {\r\n  String op(String arg) throws FooException, InterruptedException;\r\n}\r\n\r\ninterface AsyncFooClient {\r\n  Future&lt;String&gt; asyncOp(String arg, FooCompletion&lt;String&gt; callback);\r\n}\r\n\r\ninterface FooCompletion&lt;T&gt; {\r\n  void success(T result);\r\n  void failure(FooException exception);\r\n}<\/pre>\n<p>Note how the async operation \u2013 as is the case in many modern libraries \u2013 both takes a callback and returns a future. For now, let\u2019s ignore the future; we\u2019ll come back to it\u00a0later.<\/p>\n<p><code>FooClient<\/code> is a lot nicer and simpler than <code>AsyncFooClient<\/code>, but it blocks a thread and significantly reduces throughput. We want to create an implementation of the <code>FooClient<\/code> interface that can run in \u2013 and block \u2013 a fiber, so we get to have simple code <em>and<\/em> great throughput. To do that, we\u2019ll employ <code>AsyncFooClient<\/code> under the hood, but turn it into a fiber-blocking <code>FooClient<\/code>. Here\u2019s all the code we need (we\u2019re going to simplify it further in a\u00a0bit):<\/p>\n<pre class=\" brush:java\">public class FiberFooClient implements FooClient {\r\n    private final AsyncFooClient asyncClient;\r\n\r\n    public FiberFooClient(AsyncFooClient asyncClient) {\r\n        this.asyncClient = asyncClient;\r\n    }\r\n\r\n    @Override\r\n    @Suspendable\r\n    String op(final String arg) throws FooException, InterruptedException {\r\n        try {\r\n            return new FiberAsync&lt;String, FooException&gt;() {\r\n                @Override\r\n                protected void requestAsync() {\r\n                    asyncClient.asyncOp(arg, new FooCompletion&lt;String&gt;() {\r\n                        public void success(String result) {\r\n                            FiberAsync.this.asyncCompleted(result);\r\n                        }\r\n                        public void failure(FooException exception) {\r\n                            FiberAsync.this.asyncFailed(exception);\r\n                        }\r\n                    });\r\n                }\r\n            }.run();\r\n        } catch(SuspendExecution e) {\r\n            throw new AssertionError(e);\r\n        }\r\n    }\r\n}<\/pre>\n<p>Now, what\u2019s going on here? We\u2019re implementing the <code>FooClient<\/code> interface, but we\u2019re making <code>op<\/code> fiber-blocking rather than thread-blocking. We need to tell Quasar that our method is fiber-blocking (or \u201csuspendable\u201d), so we annotate it with\u00a0<code>@Suspendable<\/code>.<\/p>\n<p>Then, we\u2019re subclassing <code>FiberAsync<\/code> and implementing the <code>requestAsync<\/code> method (the two generic type arguments <code>FiberAsync<\/code> takes are the return type and the type of checked exception the operation may throw, if any; for no checked exceptions, the second generic argument should be <code>RuntimeException<\/code>). <code>requestAsync<\/code> is responsible for initiating the asynchronous operation and registering the callback. The callback, then, needs to call <code>asyncCompleted<\/code> \u2013 if the operation succeeds \u2013 and pass it the result we wish to return, or <code>asyncFailed<\/code> \u2013 if the operation fails \u2013 and pass it the exception at the cause of the\u00a0failure.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>Finally, we call <code>FiberAsync.run()<\/code>. This blocks the current fiber, and calls <code>requestAsync<\/code> to install the callback. The fiber will remain blocked until the callback is fired, which will release the <code>FiberAsync<\/code> by invoking either <code>asyncCompleted<\/code> or <code>asyncFailed<\/code>. The <code>run<\/code> method also has a version that takes a timeout argument, which can be useful if we want to time-limit the blocking operation (this is a good idea in\u00a0general).<\/p>\n<p>One more thing to explain is the <code>try\/catch<\/code> block. There are two ways of declaring a method suspendable: annotating it with <code>@Suspendable<\/code> or declaring it to throw the checked exception <code>SuspendExecution<\/code>. <code>FiberAsync<\/code>\u2019s <code>run<\/code> method employs the latter, so in order for the code to compile, we need to catch <code>SuspendExecution<\/code>, but as it\u2019s not a real exception, we can never actually catch it (well, at least not if Quasar is running correctly) \u2013 hence the\u00a0<code>AssertionError<\/code>.<\/p>\n<p>Once that\u2019s done, you can use <code>op<\/code> in any fiber, like\u00a0so:<\/p>\n<pre class=\" brush:java\">new Fiber&lt;Void&gt;(() -&gt;{\r\n    \/\/ ...\r\n    String res = client.op();\r\n    \/\/ ...\r\n}).start();<\/pre>\n<p>By the way, all of that is <em>a lot<\/em> shorter with <a href=\"https:\/\/github.com\/puniverse\/pulsar\">Pulsar<\/a> (Quasar\u2019s Clojure API), where the asynchronous\u00a0operation:<\/p>\n<pre class=\" brush:java\">(async-op arg #(println \"result:\" %))<\/pre>\n<p>Is transformed into the following, synchronous, fiber-blocking code with Pulsar\u2019s <code>await<\/code>\u00a0macro:<\/p>\n<pre class=\" brush:java\">(println \"result:\" (await (async-op arg)))<\/pre>\n<h2>Simplifying and\u00a0Mass-Producing<\/h2>\n<p>Normally, an interface like <code>FooClient<\/code> will have many methods, and normally, most of the methods in <code>AsyncFooClient<\/code> will take the same type of callback (<code>FooCompletion<\/code>). If that\u2019s the case we can encapsule much of the code we\u2019ve seen into a named subclass of\u00a0<code>FiberAsync<\/code>:<\/p>\n<pre class=\" brush:java\">abstract class FooAsync&lt;T&gt; extends FiberAsync&lt;T, FooException&gt; implements FooCompletion&lt;T&gt; {\r\n    @Override\r\n    public void success(T result) {\r\n        asyncCompleted(result);\r\n    }\r\n\r\n    @Override\r\n    public void failure(FooException exception) {\r\n        asyncFailed(exception);\r\n    }\r\n\r\n    @Override\r\n    @Suspendable\r\n    public T run() throws FooException, InterruptedException {\r\n        try {\r\n            return super.run();\r\n        } catch (SuspendExecution e) {\r\n            throw new AssertionError();\r\n        }\r\n    }\r\n\r\n    @Override\r\n    @Suspendable\r\n    public T run(long timeout, TimeUnit unit) throws FooException, InterruptedException, TimeoutException {\r\n        try {\r\n            return super.run(timeout, unit);\r\n        } catch (SuspendExecution e) {\r\n            throw new AssertionError();\r\n        }\r\n    }\r\n}<\/pre>\n<p>Note how we\u2019ve made our <code>FiberAsync<\/code> directly implement the <code>FooCompletion<\/code> callback \u2013 that\u2019s not required, but it\u2019s a useful pattern. Now, our fiber-blocking <code>op<\/code> method is a lot simpler, and other operations in that interface can be implemented just as\u00a0easily:<\/p>\n<pre class=\" brush:java\">@Override\r\n@Suspendable\r\npublic String op(final String arg) throws FooException, InterruptedException {\r\n    return new FooAsync&lt;String&gt;() {\r\n        protected void requestAsync() {\r\n            asyncClient.asyncOp(arg, this);\r\n        }\r\n    }.run();\r\n}<\/pre>\n<p>Sometimes we might like our <code>op<\/code> method to be called on regular threads, rather than on a fiber. By default, <code>FiberAsync.run()<\/code> throws an exception if called on a thread. To fix that, all we have to do is implement another <code>FiberAsync<\/code> method, <code>requestSync<\/code>, which calls the original synchronous API if <code>run<\/code> is invoked on a fiber. Our final code looks like this (we assume that the <code>FiberFooClass<\/code> has a <code>syncClient<\/code> field of type\u00a0<code>FooClient<\/code>):<\/p>\n<pre class=\" brush:java\">@Override\r\n@Suspendable\r\npublic String op(final String arg) throws FooException, InterruptedException {\r\n    return new FooAsync&lt;String&gt;() {\r\n        protected void requestAsync() {\r\n            asyncClient.asyncOp(arg, this);\r\n        }\r\n        public String requestSync() {\r\n            return syncClient.op(arg);\r\n        }\r\n    }.run();\r\n}<\/pre>\n<p>And that\u2019s\u00a0that!<\/p>\n<h2>Futures<\/h2>\n<p>Futures are a convenient way to allow several long, independent IO operations to commence simultaneously while we wait for all of them to complete. We want our fibers to be able to block on futures. Many Java libraries return futures from their asynchronous operations, so that the user is able to choose between fully asynchronous, callback-based usage, and \u201csemi-synchronous\u201d usage that employs futures; our <code>AsyncFooClient<\/code> interface works just like\u00a0that.<\/p>\n<p>This is how we implement a version of <code>AsyncFooClient<\/code> that returns fiber-blocking\u00a0futures:<\/p>\n<pre class=\" brush:java\">import co.paralleluniverse.strands.SettableFuture;\r\n\r\npublic class FiberFooAsyncClient implements FooClient {\r\n    private final AsyncFooClient asyncClient;\r\n\r\n    public FiberFooClient(AsyncFooClient asyncClient) {\r\n        this.asyncClient = asyncClient;\r\n    }\r\n\r\n    @Override\r\n    public Future&lt;String&gt; asyncOp(String arg, FooCompletion&lt;String&gt; callback) {\r\n        final SettableFuture&lt;T&gt; future = new SettableFuture&lt;&gt;();\r\n        asyncClient.asyncOp(arg, callbackFuture(future, callback))\r\n        return future;\r\n    }\r\n\r\n    private static &lt;T&gt; FooCompletion&lt;T&gt; callbackFuture(final SettableFuture&lt;T&gt; future, final FooCompletion&lt;T&gt; callback) {\r\n        return new FooCompletion&lt;T&gt;() {\r\n            @Override\r\n            public void success(T result) {\r\n                future.set(result);\r\n                callback.completed(result);\r\n            }\r\n\r\n            @Override\r\n            public void failure(Exception ex) {\r\n                future.setException(ex);\r\n                callback.failed(ex);\r\n            }\r\n\r\n            @Override\r\n            public void cancelled() {\r\n                future.cancel(true);\r\n                callback.cancelled();\r\n            }\r\n        };\r\n    }\r\n}<\/pre>\n<p>The future we return, <code>co.paralleluniverse.strands.SettableFuture<\/code>, works equally well if we block on it on either fibers or plain threads (i.e. on any type of <em>strand<\/em>).<\/p>\n<h2>JDK 8\u2019s CompletableFuture and Guava\u2019s\u00a0ListenableFuture<\/h2>\n<p>APIs that return <code>CompletionStage<\/code> (or <code>CompletableFuture<\/code> which implements it) \u2013 added to Java in JDK 8 \u2013 can be made fiber-blocking much more easily, with pre-built <code>FiberAsync<\/code>s. For\u00a0example,<\/p>\n<pre class=\" brush:java\">CompletableFuture&lt;String&gt; asyncOp(String arg);<\/pre>\n<p>is turned into a fiber-blocking call\u00a0with:<\/p>\n<pre class=\" brush:java\">String res = AsyncCompletionStage.get(asyncOp(arg));<\/pre>\n<p>Methods returning Google Guava\u2019s are similarly transformed to fiber blocking synchronous,\u00a0so:<\/p>\n<pre class=\" brush:java\">ListenableFuture&lt;String&gt; asyncOp(String arg);<\/pre>\n<p>is turned fiber-blocking\u00a0with:<\/p>\n<pre class=\" brush:java\">String res = AsyncListenableFuture.get(asyncOp(arg));<\/pre>\n<h2>An Alternative to\u00a0Futures<\/h2>\n<p>While futures are useful and familiar, we don\u2019t really need a special API that returns them when we use fibers. Fibers are so cheap to spawn \u2013 and the <code>Fiber<\/code> class implements <code>Future<\/code> \u2013 so that the fibers themselves can replace \u201chand crafted\u201d futures. Here\u2019s an\u00a0example:<\/p>\n<pre class=\" brush:java\">void work() {\r\n    Fiber&lt;String&gt; f1 = new Fiber&lt;&gt;(() -&gt; fiberFooClient.op(\"first operation\"));\r\n    Fiber&lt;String&gt; f2 = new Fiber&lt;&gt;(() -&gt; fiberFooClient.op(\"second operation\"));\r\n\r\n    String res1 = f1.get();\r\n    String res2 = f2.get();\r\n}<\/pre>\n<p>So fibers give us futures even when the APIs we\u2019re using\u00a0don\u2019t.<\/p>\n<h2>What If There\u2019s No Async\u00a0API?<\/h2>\n<p>Sometimes we unfortunately encounter a library that only provides a synchronous, thread-blocking API. JDBC is a prime example of such an API. While Quasar can\u2019t increase the throughput of working with a library like that, making the API fiber-compatible is still worthwhile (and very easy, actually). Why? Because the fibers making the calls to the synchronous service probably do other stuff as well. In fact, they might call the service rather infrequently (consider a fiber reading data from an RDBMS only when a cache-miss\u00a0occurs).<\/p>\n<p>The way to achieve this is to turn the blocking API into an asynchronous one by executing the actual calls in a dedicated thread-pool, and then wrapping that phony asynchronous API with <code>FiberAsync<\/code>. This process is so mechanical that <code>FiberAsync<\/code> has some static methods that take care of everything for us. So assume our service only exposed the blocking <code>FooClient<\/code> API. To make it fiber-blocking, all we do\u00a0is:<\/p>\n<pre class=\" brush:java\">public class SadFiberFooClient implements FooClient {\r\n    private final FooClient client;\r\n    private static final ExecutorService FOO_EXECUTOR = Executors.newCachedThreadPool();\r\n\r\n    public FiberFooClient(FooClient client) {\r\n        this.client = client;\r\n    }\r\n\r\n    @Override\r\n    @Suspendable\r\n    String op(final String arg) throws FooException, InterruptedException {\r\n        try {\r\n            return FiberAsync.runBlocking(FOO_EXECUTOR, () -&gt; client.op());\r\n        } catch(SuspendExecution e) {\r\n            throw new AssertionError(e);\r\n        }\r\n    }\r\n}<\/pre>\n<p>This implementation of <code>FooClient<\/code> is safe to use by both threads and fibers. In fact, when invoked on a plain thread, the method won\u2019t bother dispatching the operation to the supplied thread pool, but execute it on the current thread \u2013 just as would happen if we were using the original <code>FooClient<\/code>\u00a0implementation.<\/p>\n<h2>Conclusion<\/h2>\n<p>The techniques shown here \u2013 with <code>FiberAsync<\/code> and <code>c.p.strands.SettableFuture<\/code> \u2013 are exactly how the integration modules comprising the <a href=\"https:\/\/github.com\/puniverse\/comsat\">Comsat<\/a> project work. Comsat includes integrations for Servlets, JAX-RS (server and client), JDBC, JDBI, jOOQ, MongoDB, Retrofit and\u00a0Dropwizard.<\/p>\n<p>It is important to see how \u2013 to make simple and performant fiber blocking APIs \u2013 we\u2019ve indeed re-implemented the API <em>interfaces<\/em>, but not their inner workings: the original library code is still used, only through its async API, whose ugliness is now hidden from the library\u00a0consumer.<\/p>\n<h2>Extra Credit: What About\u00a0Monads?<\/h2>\n<p>There are ways other than fibers to deal with callback hell. The best known mechanisms in the JVM world are Scala\u2019s composable futures, RxJava\u2019s observables, and JDK 8\u2019s <code>CompletionStage<\/code>\/<code>CompletableFuture<\/code>. These are all examples of monads and monadic composition. Monads work, and some people enjoy using them, but I think that they\u2019re the wrong way to go for most programming\u00a0languages.<\/p>\n<p>You see, monads are borrowed from programming languages based on the lambda calculus. Lambda calculus is a theoretical model of computation, completely different from, yet entirely analogous to the Turing machine. But unlike the Turing machine model, lambda calculus computations don\u2019t have a notion of steps, actions or states. Those computations don\u2019t <em>do<\/em> anything; they just <em>are<\/em>. Monads, then, are a way for LC-based languages like Haskell to describe action, state, time etc. as pure computation. They are a way for a LC language to tell the computer \u201cdo this and then do\u00a0that\u201d.<\/p>\n<p>Thing is, imperative languages already have an abstraction for \u201cdo this and then do that\u201d, and that abstraction is the thread. Not only that, but imperative languages usually have a very simple notation for \u201cdo this and then do that\u201d: The statement for <em>this<\/em> followed by the statement for <em>that<\/em>. The only reason imperative languages even consider adopting such a foreign concept is because the implementation of threads (by the OS kernel) is less than satisfactory. But rather than adopt a foreign, unfamiliar concept \u2013 and one that requires completely different types of APIs \u2013 it\u2019s best to fix the implementation (of threads) rather than adopt a similar, yet subtly different abstraction. Fibers keep the abstraction and fix the\u00a0implementation.<\/p>\n<p>Another problem with monads in languages like Java and Scala, is that those languages are not only imperative, but allow unrestricted shared-state mutation and side effects \u2013 something that Haskell doesn\u2019t have. The combination of unrestricted shared-state mutation and \u201cthread\u201d monads can be disastrous. In a pure FP language \u2013 because side-effects are controlled \u2013 a unit of computation, namely a function, is also a unit of concurrency: you can safely execute any pair of functions concurrently. This is not the case when you have unrestricted side-effect. The order of function execution, whether or not two functions can be executed simultaneously, and if and when a function can observe the shared-state mutations performed by another, are all serious concerns. As a result, functions running as part of \u201cthread\u201d monads need to either be pure (with no side effects whatsoever) or be very-very careful about how they perform those side effects. This is exactly what we\u2019re trying to avoid. So while monadic compositions do indeed produce much nicer code than callback-hell, they don\u2019t address <em>any<\/em> of the concurrency issues introduced by asynchronous\u00a0code.<\/p>\n<p><strong>P.S.<\/strong><\/p>\n<p>The previous section should not be read as an endorsement of pure \u201cFP\u201d languages like Haskell, because I actually think they introduce too many other problems. I believe the (near) future is imperative languages <sup><a name=\"fp\">3<\/a><\/sup> that will allow shared-state mutation but with some transactional semantics. I believe those future languages will take their inspiration mostly from languages like Clojure and\u00a0Erlang.<\/p>\n<h2><a href=\"http:\/\/www.reddit.com\/r\/programming\/comments\/2ddl21\/farewell_to_asynchronous_code\/\">Discuss on\u00a0Reddit<\/a><\/h2>\n<ol>\n<li>By <em>running<\/em> I mean threads that are runnable often enough <a href=\"#num-threds\">\u21a9<\/a><\/li>\n<li>See <a href=\"http:\/\/blog.paralleluniverse.co\/2014\/02\/04\/littles-law\/\">Little\u2019s Law, Scalability and Fault Tolerance<\/a> <a href=\"#littles-law\">\u21a9<\/a><\/li>\n<li>Whether or not they are \u201cfunctional\u201d is a hard question as no one has come up with a good definition for what a functional programming language is and what differentiates it from non-functional languages. <a href=\"#fp\">\u21a9<\/a><\/li>\n<\/ol>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/blog.paralleluniverse.co\/2014\/08\/12\/noasync\/\">Farewell to Asynchronous Code<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\/\">JCG partner<\/a> Dafna Pressler at the <a href=\"http:\/\/blog.paralleluniverse.co\/\">Parallel Universe<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Quasar is a library that adds true lightweight threads (fibers) to the JVM. These are very cheap and very fast \u2013 in fact, fibers behave just like Erlang processes or Go goroutines \u2013 and allow you to write simple blocking code while enjoying the same performance benefits of complex asynchronous\u00a0code. In this post we\u2019ll learn &hellip;<\/p>\n","protected":false},"author":890,"featured_media":112,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[88,1143],"class_list":["post-39139","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-concurrency","tag-quasar"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Farewell to Asynchronous Code - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Quasar is a library that adds true lightweight threads (fibers) to the JVM. These are very cheap and very fast \u2013 in fact, fibers behave just like Erlang\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Farewell to Asynchronous Code - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Quasar is a library that adds true lightweight threads (fibers) to the JVM. These are very cheap and very fast \u2013 in fact, fibers behave just like Erlang\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-04-15T19:00:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Ron Pressler\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ron Pressler\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html\"},\"author\":{\"name\":\"Ron Pressler\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/cf2878570fc4ac8ed22569ad7718ec78\"},\"headline\":\"Farewell to Asynchronous Code\",\"datePublished\":\"2015-04-15T19:00:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html\"},\"wordCount\":2211,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"keywords\":[\"Concurrency\",\"Quasar\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html\",\"name\":\"Farewell to Asynchronous Code - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"datePublished\":\"2015-04-15T19:00:44+00:00\",\"description\":\"Quasar is a library that adds true lightweight threads (fibers) to the JVM. These are very cheap and very fast \u2013 in fact, fibers behave just like Erlang\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"java-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/04\\\/farewell-to-asynchronous-code.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Farewell to Asynchronous Code\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/cf2878570fc4ac8ed22569ad7718ec78\",\"name\":\"Ron Pressler\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4650659b92f3389fab6185fa4d83bc150c6a14efc8307608285a386faace2e93?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4650659b92f3389fab6185fa4d83bc150c6a14efc8307608285a386faace2e93?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4650659b92f3389fab6185fa4d83bc150c6a14efc8307608285a386faace2e93?s=96&d=mm&r=g\",\"caption\":\"Ron Pressler\"},\"description\":\"Ron Pressler is the founder of Parallel Universe, a company building a JVM-based server-side stack for easily writing high-performance, low latency applications that work in harmony with modern hardware architecture.\",\"sameAs\":[\"http:\\\/\\\/blog.paralleluniverse.co\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/ron-pressler\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Farewell to Asynchronous Code - Java Code Geeks","description":"Quasar is a library that adds true lightweight threads (fibers) to the JVM. These are very cheap and very fast \u2013 in fact, fibers behave just like Erlang","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html","og_locale":"en_US","og_type":"article","og_title":"Farewell to Asynchronous Code - Java Code Geeks","og_description":"Quasar is a library that adds true lightweight threads (fibers) to the JVM. These are very cheap and very fast \u2013 in fact, fibers behave just like Erlang","og_url":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2015-04-15T19:00:44+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","type":"image\/jpeg"}],"author":"Ron Pressler","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Ron Pressler","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html"},"author":{"name":"Ron Pressler","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/cf2878570fc4ac8ed22569ad7718ec78"},"headline":"Farewell to Asynchronous Code","datePublished":"2015-04-15T19:00:44+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html"},"wordCount":2211,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","keywords":["Concurrency","Quasar"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html","url":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html","name":"Farewell to Asynchronous Code - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","datePublished":"2015-04-15T19:00:44+00:00","description":"Quasar is a library that adds true lightweight threads (fibers) to the JVM. These are very cheap and very fast \u2013 in fact, fibers behave just like Erlang","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","width":150,"height":150,"caption":"java-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2015\/04\/farewell-to-asynchronous-code.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Farewell to Asynchronous Code"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/cf2878570fc4ac8ed22569ad7718ec78","name":"Ron Pressler","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4650659b92f3389fab6185fa4d83bc150c6a14efc8307608285a386faace2e93?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4650659b92f3389fab6185fa4d83bc150c6a14efc8307608285a386faace2e93?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4650659b92f3389fab6185fa4d83bc150c6a14efc8307608285a386faace2e93?s=96&d=mm&r=g","caption":"Ron Pressler"},"description":"Ron Pressler is the founder of Parallel Universe, a company building a JVM-based server-side stack for easily writing high-performance, low latency applications that work in harmony with modern hardware architecture.","sameAs":["http:\/\/blog.paralleluniverse.co\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/ron-pressler"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/39139","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/890"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=39139"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/39139\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/112"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=39139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=39139"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=39139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}