208

I am a normal C# developer but occasionally I develop application in Java. I'm wondering if there is any Java equivalent of C# async/await? In simple words what is the java equivalent of:

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();
    var urlContents = await client.GetStringAsync("http://msdn.microsoft.com");
    return urlContents.Length;
}
mehrandvd
  • 8,806
  • 12
  • 64
  • 111
Imran Qadir Baksh - Baloch
  • 32,612
  • 68
  • 179
  • 322
  • 9
    Why this would be nice: [Callbacks as our Generations’ Go To Statement](http://tirania.org/blog/archive/2013/Aug-15.html) by Miguel de Icaza. – andrewdotn Nov 12 '13 at 04:00
  • Java's current solution is to not deal with actual values prefixed with `async`, but use `Future` or `Observable` values instead. – S.D. Feb 23 '18 at 04:32
  • 5
    There is no equivalent. And it hurts. One more missing feature you need complicated workarounds and libraries for, without ever reaching the same effect as these two, simple words. – spyro Dec 12 '19 at 17:35
  • It's worth noting that for a long time, Java designers have tried to keep the Java bytecode backward compatible with only changes to libraries and Syntatic-sugar around existing features. *See the fact that generics don't store run-time type information and lambders are implemented as object implementing an interface*. async/await would require very large changes to the bytecode to be possible and therefore I wouldn't expect to see it in java any time soon. – Philip Couling Feb 21 '20 at 14:10
  • 1
    @PhilipCouling I don't believe there is any need to do any change in the bytecode to support async await. It's just syntactic sugar around Futures, nothing more. As a matter of fact, in JavaScript, you can transpile your async/await code in Future equivalent for backward compatibility. It's just about building a state machine, which you can do by generating bytecode. No need for changes in the JVM. – pieroxy Aug 27 '21 at 13:52
  • @pieroxy Java and JavaScript are very different. JavaScript has yield which can be used to implement await. last time I checked Java does not. As a matter of fact yield is how python first achieved async. But without yield it's near impossible to stop what you're doing, save the stack, do something completely different then restore the stack and carry on all on the same thread. It's just not how the nvm works. – Philip Couling Aug 27 '21 at 17:20
  • @pieroxy just to be clear async/await is **not** syntactic sugar to a language with no yield. It's a fundamental construct. – Philip Couling Aug 27 '21 at 17:29
  • @PhilipCouling As far as I understand it, python and javascript need yield because they do not have multithreading. Java having multithreading since day one, I don't believe yield would be of any necessity. Just transforming all the code after an async to a callback is all that is needed. Fundamentally, async/await is just another way of writing Future and callbacks, but this time the code is linear instead of all over the place. There are shenanigans with exceptions and other things of course. – pieroxy Aug 30 '21 at 08:38
  • 1
    @pieroxy no **async is not multithreading** and python had multithreading long before async. Multithreading uses operating system threads and the OS time slices between them. Async uses a single OS thread and the application takes responsibility to switch tasks when a task reaches a logical point where it must stop ( eg network read). The whole point of async is that it it reuses the same thread to perform other tasks while a task is blocking. The lack of threading is purely a JavaScript thing. – Philip Couling Aug 30 '21 at 09:00
  • 1
    @PhilipCouling Thanks for the clarification. That said, C# async await implementation does *not* guarantee the continuation is going to be done on the same thread. It's just syntactic sugar on top of Promises - so I guess your mileage may vary depending on which language you use. And Java could very well implement the C# flavor of async/await. – pieroxy Aug 30 '21 at 09:10
  • 2
    @pieroxy still no. Even in c# the core concept remains the same and is not syntactic sugar ([as described by jon skeet](https://stackoverflow.com/a/16539332/453851)). Sure multiple threads may execute tasks from the same pool but that doesn't mean async is a threading model. Async is hard to understand and many people don't. In all languages that support async; `await` can suspend the entire call stack of the task and executes something different on the same thread. In java you just can't suspend the stack and restore it later. – Philip Couling Aug 30 '21 at 10:33
  • @PhilipCouling So what you are saying is that the [ea-async](https://github.com/electronicarts/ea-async) library is not actually implementing async await as they claim they do (apart from having parenthesis where none should be if it was in the language directly) ? For me, the real benefit of async/await is to write async code in a sequential fashion, instead of having callbacks all over the place, and that lib does it. What feature of async/await is missing here? And can you advise me on some reading on the topic so I'll stop bugging you here? – pieroxy Aug 30 '21 at 12:49
  • @pieroxy ea-async modifies the byte code via instrumentation AFAIK. Thus my original point stands. A lot of async documentation is a bit vague. C# has some reasonable docs (https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/) but I struggle to find the ones that helped me most originally. – Philip Couling Aug 30 '21 at 22:24
  • @PhilipCouling If we assume ea-async does properly async/await, it proves my point, not yours. The fact that they modify the bytecode is irrelevant. It just shows there is a way to emmit bytecode that can do async/await with a current JVM, no need to change the JVM, just the compiler to emmit the proper bytecode. Thanks for the doc, I'm jumping in. – pieroxy Aug 31 '21 at 05:11
  • @pieroxy my original point, that you have continually argued with, is [you can't do this without modifying the byte code](https://stackoverflow.com/questions/16539245/java-equivalent-of-c-sharp-async-await?noredirect=1#comment106738298_16539245) ... a library modifying the byte code does not prove me wrong. Historically java designers have avoided such changes. I think i'll leave this there. – Philip Couling Aug 31 '21 at 08:10
  • @PhilipCouling Right, that was your original point, my bad. My point was just that Kotlin has async/await and runs on the JVM, so there is nothing to do in the JVM and bytecode intepretation/runtime for Java to support async/await. Of course, if they were to implement this, it would generate new bytecode, but I fail to see where that's a problem. Your analogy with Generics doesn't hold here because the JVM doesn't support them at runtime. And Kotlin can call Java and Java Kotlin so there is no compatibility issue in any way. Supporting them in Java libs would be the real work. – pieroxy Sep 01 '21 at 04:33
  • If your programming language is strong enough to support writing an event loop, then it's possible to write async/await as merely generating code for a state-machine (sytactic sugar). If some language implementation takes it a step further by letting some runtime system determine if an event loop or different thread is used, or if there are multiple event-loops guaranteed, then you're missing the point of async/await. Supporting generics is a different story - in C# at least it would require modifying the syntax and semantics of metadata. – Nathan Chappell Nov 20 '22 at 18:16

14 Answers14

179

No, there isn't any equivalent of async/await in Java - or even in C# before v5.

It's a fairly complex language feature to build a state machine behind the scenes.

There's relatively little language support for asynchrony/concurrency in Java, but the java.util.concurrent package contains a lot of useful classes around this. (Not quite equivalent to the Task Parallel Library, but the closest approximation to it.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks. Is there any third party library for that? or any plan for the upcoming java – Imran Qadir Baksh - Baloch May 14 '13 at 09:19
  • 19
    @user960567: No, my point is that it's a *language* feature - it can't be put solely in libraries. I don't believe there's any equivalent scheduled for Java 8 at least. – Jon Skeet May 14 '13 at 09:23
  • Sorry, but for your comment "even in C# before v5", I think with Microsoft.Bcl.Async we can use async await in .NET 4.0 – Imran Qadir Baksh - Baloch May 14 '13 at 09:30
  • 12
    @user960567: You need to distinguish between the version of C# you're using and the version of .NET you're using. async/await is a *language* feature - it was introduced in C# 5. Yes, you can use Microsoft.Bcl.Async to use async/await targeting .NET 4, but you've still got to use a C# 5 compiler. – Jon Skeet May 14 '13 at 09:31
  • @JonSkeet Can we say netflix's RX https://github.com/Netflix/RxJava will accomplish the asynchronous we are expecting – rozar Mar 26 '14 at 06:27
  • 6
    @rozar: No, not really. There are already multiple options for asynchrony - but RxJava doesn't change the *language* in the way that C# did. I have nothing against Rx, but it's not the same thing as async in C# 5. – Jon Skeet Mar 26 '14 at 06:46
  • @JonSkeet you do agree that the JVM is highly concurrent and possesses many asynchronous mechanisms .. right? – DtechNet Oct 21 '15 at 00:01
  • 11
    @DtechNet: Well there's a lot of JVM machinery which is asynchronous, yes... that's very different from there being *actual language features* supporting asynchrony though. (There was a lot of asynchrony in .NET before async/await, too... but async/await makes it *far* easier to take advantage of that.) – Jon Skeet Oct 21 '15 at 05:45
  • I know this thread is old, but I think the answer marked as correct is outdated. There are solutions pointed out in the other answers which do not match the async/await syntax by 100%, but get fairly close. – Aarkon Jun 11 '19 at 09:36
  • 5
    @Aarkon: I would argue that unless there's explicit *language* support, the answer is still correct. It's not just a matter of libraries that make scheduling simpler - the whole way the C# compiler builds a state machine is important here. – Jon Skeet Jun 11 '19 at 11:09
  • Agreed, your answer is still technically correct and for sure you have a point saying that library support is something different than on the language core. Yet, since the original question was if there is "any Java equivalent" to async/await, it feels incomplete to me. – Aarkon Jun 11 '19 at 14:55
  • 1
    @Aarkon: The third paragraph explicitly talks about there being no *language* equivalent, but a bunch of classes already in the base libraries. I'm content with this answer - I don't intend to change it. – Jon Skeet Jun 11 '19 at 15:38
  • At least to me, reading your answer, it didn't feel like what I was looking for already knowing there were some libraries around that make it relatively easy to write async java. But of course, your mileage may vary. – Aarkon Jun 13 '19 at 10:04
  • 3
    @MohamedIqzas: Those aren't really equivalent to async/await. There are plenty of ways of writing parallel and/or asynchronous code in Java, but async/await provides additional *language-level* support that makes a big difference. – Jon Skeet Jun 26 '20 at 06:30
  • 1
    It's 2020 now and whoever still wants async/await in Java, you can simply use Kotlin and Kotlin coroutines. Fortunately it has Java interpolability. – dephinera Oct 15 '20 at 21:18
53

The await uses a continuation to execute additional code when the asynchronous operation completes (client.GetStringAsync(...)).

So, as the most close approximation I would use a CompletableFuture<T> (the Java 8 equivalent to .net Task<TResult>) based solution to process the Http request asynchronously.

UPDATED on 25-05-2016 to AsyncHttpClient v.2 released on Abril 13th of 2016:

So the Java 8 equivalent to the OP example of AccessTheWebAsync() is the following:

CompletableFuture<Integer> AccessTheWebAsync()
{
    AsyncHttpClient asyncHttpClient = new DefaultAsyncHttpClient();
    return asyncHttpClient
       .prepareGet("http://msdn.microsoft.com")
       .execute()
       .toCompletableFuture()
       .thenApply(Response::getResponseBody)
       .thenApply(String::length);
}

This usage was taken from the answer to How do I get a CompletableFuture from an Async Http Client request? and which is according to the new API provided in version 2 of AsyncHttpClient released on Abril 13th of 2016, that has already intrinsic support for CompletableFuture<T>.

Original answer using version 1 of AsyncHttpClient:

To that end we have two possible approaches:

  • the first one uses non-blocking IO and I call it AccessTheWebAsyncNio. Yet, because the AsyncCompletionHandler is an abstract class (instead of a functional interface) we cannot pass a lambda as argument. So it incurs in inevitable verbosity due to the syntax of anonymous classes. However, this solution is the most close to the execution flow of the given C# example.

  • the second one is slightly less verbose however it will submit a new Task that ultimately will block a thread on f.get() until the response is complete.

First approach, more verbose but non-blocking:

static CompletableFuture<Integer> AccessTheWebAsyncNio(){
    final AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
    final CompletableFuture<Integer> promise = new CompletableFuture<>();
    asyncHttpClient
        .prepareGet("https://msdn.microsoft.com")
        .execute(new AsyncCompletionHandler<Response>(){
            @Override
            public Response onCompleted(Response resp) throws Exception {
                promise.complete(resp.getResponseBody().length());
                return resp;
            }
        });
    return promise;
}

Second approach less verbose but blocking a thread:

static CompletableFuture<Integer> AccessTheWebAsync(){
    try(AsyncHttpClient asyncHttpClient = new AsyncHttpClient()){
        Future<Response> f = asyncHttpClient
            .prepareGet("https://msdn.microsoft.com")
            .execute();
        return CompletableFuture.supplyAsync(
            () -> return f.join().getResponseBody().length());
    }
}
Community
  • 1
  • 1
Miguel Gamboa
  • 8,855
  • 7
  • 47
  • 94
  • 4
    Actually, that's the equivalent of the happy flow. It doesn't cover handling exceptions, finally and others. Including them will make the code much more complex and more prone to errors. – haimb Jan 16 '19 at 06:20
  • 6
    This isn't a continuation. This example misses the real purpose of async/await, which is to release the current thread to execute other things, and then to continue execution of this method on the current thread after a response arrives. (This is either necessary for the UI thread to be responsive, or to reduce memory usage.) What this example does is a plain blocking thread synchronization, plus some callbacks. – Aleksandr Dubinsky Nov 12 '19 at 21:52
  • 1
    @AleksandrDubinsky I agree with you when you point that the callback may not run on the caller thread. You are right. I disagree about blocking a thread. My updated answer of _UPDATED on 25-05-2016_ is non-blocking. – Miguel Gamboa Nov 13 '19 at 13:37
  • 2
    .... and this sample is exactly the reason why C# is so much simpler to write and read when doing asynchronous stuff. It's just a pain in Java. – spyro Dec 12 '19 at 17:37
16

There is no equivalent of C# async/await in Java at the language level. A concept known as Fibers aka cooperative threads aka lightweight threads could be an interesting alternative. You can find Java libraries providing support for fibers.

Java libraries implementing Fibers

You can read this article (from Quasar) for a nice introduction to fibers. It covers what threads are, how fibers can be implemented on the JVM and has some Quasar specific code.

FabienB
  • 1,104
  • 2
  • 11
  • 22
  • 12
    async/await in C# is not a Fiber. It just compiler magic that use continuation on Promise (the `Task` class) by registering a callback. – UltimaWeapon Jun 27 '16 at 05:59
  • 1
    @UltimaWeapon So what do you consider to be fibers? – Aleksandr Dubinsky Dec 14 '18 at 16:09
  • @AleksandrDubinsky One of the example is goroutine. – UltimaWeapon Dec 15 '18 at 10:19
  • 1
    @UltimaWeapon I was looking for an explanation. – Aleksandr Dubinsky Dec 16 '18 at 08:36
  • @AleksandrDubinsky I'm lazy to explain it. If you really want to know you may search the article about under the hood of goroutine. – UltimaWeapon Dec 16 '18 at 15:05
  • C# async/await use is nothing to do with Fibers. It is compiler-support for simplification of callbacks used in asynchronous I/O, not for asynchronous computation state management. – Tony B May 27 '19 at 16:02
  • Asynchrony and Concurency are not same, async is related to not waiting for a task to complete before going on with the program flow this has nothing to do with threading, it can be done on same thread. Concurreny is the ability to run multiple tasks at the same time which is what threading is all about. – Surya Pratap Jul 03 '19 at 07:42
15

async and await are syntactic sugars. The essence of async and await is state machine. The compiler will transform your async/await code into a state machine.

At the same time, in order for async/await to be really practicable in real projects, we need to have lots of Async I/O library functions already in place. For C#, most original synchronized I/O functions has an alternative Async version. The reason we need these Async functions is because in most cases, your own async/await code will boil down to some library Async method.

The Async version library functions in C# is kind of like the AsynchronousChannel concept in Java. For example, we have AsynchronousFileChannel.read which can either return a Future or execute a callback after the read operation is done. But it’s not exactly the same. All C# Async functions return Tasks (similar to Future but more powerful than Future).

So let’s say Java do support async/await, and we write some code like this:

public static async Future<Byte> readFirstByteAsync(String filePath) {
    Path path = Paths.get(filePath);
    AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);

    ByteBuffer buffer = ByteBuffer.allocate(100_000);
    await channel.read(buffer, 0, buffer, this);
    return buffer.get(0);
}

Then I would imagine the compiler will transform the original async/await code into something like this:

public static Future<Byte> readFirstByteAsync(String filePath) {

    CompletableFuture<Byte> result = new CompletableFuture<Byte>();

    AsyncHandler ah = new AsyncHandler(result, filePath);

    ah.completed(null, null);

    return result;
}

And here is the implementation for AsyncHandler:

class AsyncHandler implements CompletionHandler<Integer, ByteBuffer>
{
    CompletableFuture<Byte> future;
    int state;
    String filePath;

    public AsyncHandler(CompletableFuture<Byte> future, String filePath)
    {
        this.future = future;
        this.state = 0;
        this.filePath = filePath;
    }

    @Override
    public void completed(Integer arg0, ByteBuffer arg1) {
        try {
            if (state == 0) {
                state = 1;
                Path path = Paths.get(filePath);
                AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);

                ByteBuffer buffer = ByteBuffer.allocate(100_000);
                channel.read(buffer, 0, buffer, this);
                return;
            } else {
                Byte ret = arg1.get(0);
                future.complete(ret);
            }

        } catch (Exception e) {
            future.completeExceptionally(e);
        }
    }

    @Override
    public void failed(Throwable arg0, ByteBuffer arg1) {
        future.completeExceptionally(arg0);
    }
}
caisx25
  • 363
  • 2
  • 4
  • 26
    Syntatic sugar? Do you have any idea about how to wrap exceptions around async code, and loops around async code? – Akash Kava Jul 29 '16 at 11:31
  • 67
    Classes, too, are syntactic sugar. The compiler creates all the trees and lists of function pointers you would normally write by hand for you fully automatically. These functions / methods are syntactic sugar, too. They auto-generate all the gotos you would normally, being a real programmer, write by hand. Assembler is syntactic sugar, too. Real programmers manually write machine code and manually port it to all target architectures. – yeoman Oct 11 '16 at 12:31
  • 51
    Thinking abou itt, computers themselves are just syntactic sugar for l4m3 n00bz. Real programmers solder them tiny integrated circuits to a wooden board and connect them with gold wire because circuit boards are syntactic sugar, just like mass production, shoes, or food. – yeoman Oct 11 '16 at 12:35
  • 3
    Right, syntactic sugar that reduces the amount of code to maintain, understand, and step through by a couple orders of magnitude is *so* hipster. – user1969177 Sep 19 '21 at 14:17
  • Something can only be called syntactic sugar when it's possible to write equivalent code that doesn't use it. That's not the case here, the things going on behind the scenes in async/await have no way to be expressed using java syntax. – entonio Nov 28 '22 at 00:50
  • .Net already had async methods in place before the introduction of async/await. And I believe java has them as well. And writing a wrapper that converts the old async methods to async/await is fairly simple. – Ykok May 22 '23 at 11:28
  • @entonio I'm not totally sure about Java, but everything that is being done in .Net/C# now with async/await could be done before it was introduced. It would look really ugly and be hard to read, but in theory it can be done. – Ykok May 22 '23 at 11:31
  • @Ykok a number of answers in this very page explain why async/await is fundamentally different from the regular 'async patterns' you may find everywhere. I'm not going to rehash it, the core of it is Java (still) has no yield or any other interruption+continuation mechanism. In fact, the only reason I'm pointing it out is that it can lead someone to read up on how async/await really works, which is an eye opener. – entonio May 23 '23 at 23:06
  • @entonio Before async/await was introduced, there were already asynchronous I/O libraries in C# ([example](https://learn.microsoft.com/en-us/dotnet/api/system.net.webclient.downloadstringasync?view=netframework-3.5)). Hence since async/await is syntactic sugar as you write, and the framework already supported asynchronous communication - then you could in fact implement the exact same functionality (which I've tried in a demonstration project). Furthermore by utilizing the `TaskCompletionSource` you can actually wrap old asynchronous so you can expose them as methods using async/await pattern. – Ykok May 25 '23 at 05:40
  • @entonio looking at java documentation there is the whole nio library - which is a non-blocking io library that's been available since java 7. This looks to support asynchronous I/O in the same sense as C# has always done. This means that implementing async/await in java could be as easy as implementing a syntactic sugar layer. – Ykok May 25 '23 at 05:49
  • @Ykok you can spend all day looking for async libraries we all know about or you can spend a few minutes in this very page reading how async/await works and understanding why it is not a matter of syntactic sugar. – entonio May 26 '23 at 12:42
  • @entonio I understand async/await quite well thank you. And async/await **is** in fact syntactic sugar. As I wrote I have implementing the same logic with and without async/await. I suggest you read up on async/await. You can start [on this microsoft page](https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/async-scenarios) where it states "the compiler transforms your code into a state machine". On this page there is also a link to a microsoft developer who has written a [page on how async/await works](https://devblogs.microsoft.com/dotnet/how-async-await-really-works/). – Ykok May 27 '23 at 20:30
  • @Ykok if you read your second link, you should know what `yield` is. Java has no `yield`. – entonio May 28 '23 at 15:54
  • Here's an explanation of how async/await work differently from the callback pattern: https://blog.stephencleary.com/2013/11/there-is-no-thread.html – entonio May 28 '23 at 15:58
  • @entonio Even though Java has no `yield` it is still possible to utilize the callback mechanism and create code that executes as if you had written async/await. You can still write what you meant to write after `await` in your callback method (it would still be rather unreadable). – Ykok May 31 '23 at 19:59
  • @entonio Great article (I've read it before, and I've written with author in the past). And I agree that the two patterns are different and doesn't look alike. They just accomplish the same thing when used for asynchronous methods. – Ykok May 31 '23 at 20:08
9

As it was mentioned, there is no direct equivalent, but very close approximation could be created with Java bytecode modifications (for both async/await-like instructions and underlying continuations implementation).

I'm working right now on a project that implements async/await on top of JavaFlow continuation library, please check https://github.com/vsilaev/java-async-await

No Maven mojo is created yet, but you may run examples with supplied Java agent. Here is how async/await code looks like:

public class AsyncAwaitNioFileChannelDemo {

public static void main(final String[] argv) throws Exception {

    ...
    final AsyncAwaitNioFileChannelDemo demo = new AsyncAwaitNioFileChannelDemo();
    final CompletionStage<String> result = demo.processFile("./.project");
    System.out.println("Returned to caller " + LocalTime.now());
    ...
}


public @async CompletionStage<String> processFile(final String fileName) throws IOException {
    final Path path = Paths.get(new File(fileName).toURI());
    try (
            final AsyncFileChannel file = new AsyncFileChannel(
                path, Collections.singleton(StandardOpenOption.READ), null
            );              
            final FileLock lock = await(file.lockAll(true))
        ) {

        System.out.println("In process, shared lock: " + lock);
        final ByteBuffer buffer = ByteBuffer.allocateDirect((int)file.size());

        await( file.read(buffer, 0L) );
        System.out.println("In process, bytes read: " + buffer);
        buffer.rewind();

        final String result = processBytes(buffer);

        return asyncResult(result);

    } catch (final IOException ex) {
        ex.printStackTrace(System.out);
        throw ex;
    }
}

@async is the annotation that flags a method as asynchronously executable, await() is a function that waits on CompletableFuture using continuations and a call to "return asyncResult(someValue)" is what finalizes associated CompletableFuture/Continuation

As with C#, control flow is preserved and exception handling may be done in regular manner (try/catch like in sequentially executed code)

Valery Silaev
  • 199
  • 2
  • 4
7

Java itself has no equivalent features, but third-party libraries exist which offer similar functionality, e.g.Kilim.

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38
7

Java doesn't have direct equivalent of C# language feature called async/await, however there's a different approach to the problem that async/await tries to solve. It's called project Loom, which will provide virtual threads for high-throughput concurrency. It will be available in some future version of OpenJDK.

This approach also solves "colored function problem" that async/await has.

Similar feature can be also found in Golang (goroutines).

Martin Obrátil
  • 214
  • 3
  • 9
  • 2
    I'm looking forward to this. I'm learning Java, coming from Node.js and Go, and this is painful. Node.js has async/await (the colored function problem never bothered me much) and Go has goroutines so you just write blocking code in the millions of cheap goroutines you spawn. Java seems to have neither and needs me to use things like java.util.concurrent or RxJava to make my code non-blocking. If my understanding of Project Loom is correct, it'll make coding asynchronous things in Java as easy as Go. You'd just write blocking code without worrying about running out of "threads" able to execute. – Matt Welke May 29 '21 at 18:14
  • 1
    @MattWelke Yes, that's correct understanding. – Martin Obrátil Aug 11 '21 at 15:10
6

First, understand what async/await is. It is a way for a single-threaded GUI application or an efficient server to run multiple "fibers" or "co-routines" or "lightweight threads" on a single thread. Of note is that it uses the cooperative form of multi-threading, as opposed to pre-emptive. It is meant to solve one of two, separate issues. The first is that the framework developer found it too hard to do concurrent programming (typical of GUI frameworks). The second is that OS threads have too much overhead, particularly memory usage (typical of server frameworks).

In case you don't have either problem, then just use regular OS multi-threading. This is often easier and faster than asynchronous programming. To launch threads, consider using ExecutorService.submit and Future.get or the upcoming StructuredTaskScope. Inside of those threads, use ordinary synchronous, blocking calls.

In case your problem is scalability and OS thread overhead, then know that Java 21 offers "virtual" threads. These are a lot like OS threads, but use much less memory. Go has a similar feature called goroutines.

For older versions of Java, you'll need to look to your framework, which has likely implemented some sort of "asynchronous" optimization. Many frameworks have done this, including Servlet 3.0. These don't have the elegance of language features, though. They work through ordinary callbacks.

In case your problem is concurrency, then you likewise need to look at your framework. For example, JavaFX offers javafx.concurrent.Task.

Aleksandr Dubinsky
  • 22,436
  • 15
  • 82
  • 99
  • 3
    Here is an article quote restarting this answer's first paragraph //start quote For client applications, such as Windows Store, Windows desktop and Windows Phone apps, the primary benefit of async is responsiveness. These types of apps use async chiefly to keep the UI responsive. For server applications, the primary benefit of async is scalability. https://msdn.microsoft.com/en-us/magazine/dn802603.aspx – granadaCoder Dec 12 '18 at 18:46
4

There is an "equivalent" of await developed by EA: https://github.com/electronicarts/ea-async. Refer to the Java example code:

import static com.ea.async.Async.await;
import static java.util.concurrent.CompletableFuture.completedFuture;

public class Store
{
    public CompletableFuture<Boolean> buyItem(String itemTypeId, int cost)
    {
        if(!await(bank.decrement(cost))) {
            return completedFuture(false);
        }
        await(inventory.giveItem(itemTypeId));
        return completedFuture(true);
    }
}
walter33
  • 776
  • 5
  • 12
3

There isn't anything native to java that lets you do this like async/await keywords, but what you can do if you really want to is use a CountDownLatch. You could then imitate async/await by passing this around (at least in Java7). This is a common practice in Android unit testing where we have to make an async call (usually a runnable posted by a handler), and then await for the result (count down).

Using this however inside your application as opposed to your test is NOT what I am recommending. That would be extremely shoddy as CountDownLatch depends on you effectively counting down the right number of times and in the right places.

stevebot
  • 23,275
  • 29
  • 119
  • 181
3

I make and released Java async/await library. https://github.com/stofu1234/kamaitachi

This library don't need compiler extension, and realize stackless IO processing in Java.

    async Task<int> AccessTheWebAsync(){ 
        HttpClient client= new HttpClient();
        var urlContents= await client.GetStringAsync("http://msdn.microsoft.com");
       return urlContents.Length;
    }

   ↓

    //LikeWebApplicationTester.java
    BlockingQueue<Integer> AccessTheWebAsync() {
       HttpClient client = new HttpClient();
       return awaiter.await(
            () -> client.GetStringAsync("http://msdn.microsoft.com"),
            urlContents -> {
                return urlContents.length();
            });
    }
    public void doget(){
        BlockingQueue<Integer> lengthQueue=AccessTheWebAsync();
        awaiter.awaitVoid(()->lengthQueue.take(),
            length->{
                System.out.println("Length:"+length);
            }
            );
    }
stofu
  • 31
  • 1
  • How would you handle String x = await f(); if(x == "Facebook") { LongAsyncFuncToRunFacebook();} else {LongAsyncFuncToRunSomethingElse();} AfterIfElseRunSomethingNewJustForFun(); – pratikpc Jan 04 '21 at 04:15
1

Java has unfortunately no equivalent of async/await. The closest you can get is probably with ListenableFuture from Guava and listener chaining, but it would be still very cumbersome to write for cases involving multiple asynchronous calls, as the nesting level would very quickly grow.

If you're ok with using a different language on top of JVM, fortunately there is async/await in Scala which is a direct C# async/await equivalent with an almost identical syntax and semantics: https://github.com/scala/async/

Note that although this functionality needed a pretty advanced compiler support in C#, in Scala it could be added as a library thanks to a very powerful macro system in Scala and therefore can be added even to older versions of Scala like 2.10. Additionally Scala is class-compatible with Java, so you can write the async code in Scala and then call it from Java.

There is also another similar project called Akka Dataflow http://doc.akka.io/docs/akka/2.3-M1/scala/dataflow.html which uses different wording but conceptually is very similar, however implemented using delimited continuations, not macros (so it works with even older Scala versions like 2.9).

Piotr Kołaczkowski
  • 2,601
  • 12
  • 14
0

If you're just after clean code which simulates the same effect as async/await in java and don't mind blocking the thread it is called on until it is finished, such as in a test, you could use something like this code:

interface Async {
    void run(Runnable handler);
}

static void await(Async async) throws InterruptedException {

    final CountDownLatch countDownLatch = new CountDownLatch(1);
    async.run(new Runnable() {

        @Override
        public void run() {
            countDownLatch.countDown();
        }
    });
    countDownLatch.await(YOUR_TIMEOUT_VALUE_IN_SECONDS, TimeUnit.SECONDS);
}

    await(new Async() {
        @Override
        public void run(final Runnable handler) {
            yourAsyncMethod(new CompletionHandler() {

                @Override
                public void completion() {
                    handler.run();
                }
            });
        }
    });
Pellet
  • 2,254
  • 1
  • 28
  • 20
0

I have developed a library JAsync to do this. It is just released today. It makes the developer's asynchronous programming experience as close as possible to the usual synchronous programming, including code style and debugging. Here is the example.

@RestController
@RequestMapping("/employees")
public class MyRestController {
    @Inject
    private EmployeeRepository employeeRepository;
    @Inject
    private SalaryRepository salaryRepository;

    // The standard JAsync async method must be annotated with the Async annotation, and return a Promise object.
    @Async()
    private Promise<Double> _getEmployeeTotalSalaryByDepartment(String department) {
        double money = 0.0;
        // A Mono object can be transformed to the Promise object. So we get a Mono object first.
        Mono<List<Employee>> empsMono = employeeRepository.findEmployeeByDepartment(department);
        // Transformed the Mono object to the Promise object.
        Promise<List<Employee>> empsPromise = JAsync.from(empsMono);
        // Use await just like es and c# to get the value of the Promise without blocking the current thread.
        for (Employee employee : empsPromise.await()) {
            // The method findSalaryByEmployee also return a Mono object. We transform it to the Promise just like above. And then await to get the result.
            Salary salary = JAsync.from(salaryRepository.findSalaryByEmployee(employee.id)).await();
            money += salary.total;
        }
        // The async method must return a Promise object, so we use just method to wrap the result to a Promise.
        return JAsync.just(money);
    }

    // This is a normal webflux method.
    @GetMapping("/{department}/salary")
    public Mono<Double> getEmployeeTotalSalaryByDepartment(@PathVariable String department) { 
        // Use unwrap method to transform the Promise object back to the Mono object.
        return _getEmployeeTotalSalaryByDepartment(department).unwrap(Mono.class);
    }
}

And in debug mode, you can see all the variable just like the synchronous code.

enter image description here

The other great thing about this project is that it's one of the few projects of its kind that's still active right now. It's just been released, so it has a lot of potential

vipcxj
  • 840
  • 5
  • 10