devoured elysium
devoured elysium

Reputation: 105067

Java's equivalent to Scala's futures?

I'm looking for what the equivalent to Scala's futures is in Java.

I'm looking for a type of construct that allows me to submit tasks (Runnables / Callables) to a specific thread-pool of my choice, returning futures allowing me to chain some logic (in a non-blocking way) to it when it gets completed. Something like this:

var executor = Executors.newCachedThreadPool();
executor.submit(() -> {
  Thread.sleep(5000);
  return 666;
}.onComplete(v -> System.out.println(v));

Java's thread-pools (available through the Executors singleton) seem to always return standard Java Futures, which only allow me to call a blocking get(). On the other hand, the CompletableFuture, from what I can understand, is more akin to Scala's promises, and is not tied to a thread-pool.

Does Java provide what I'm looking for? How do people in Java-land deal with these kinds of operations?

Upvotes: 0

Views: 469

Answers (1)

rzwitserloot
rzwitserloot

Reputation: 102902

You want callback hell? That's a new one.

from what I can understand, is more akin to Scala's promises, and is not tied to a thread-pool.

Incorrect. I think CompletableFuture is precisely what you want :)

There is a default executor that will be used, but you can also specify one explicitly if you prefer - the supplyAsync and runAsync methods have overloads where you can pass in an explicit executor instead, and all the stuff in the chain uses whatever the future you're chaining off of uses.

CompletableFuture.supplyAsync(() -> {
    Thread.sleep(5000);
    System.out.println("Helloooo there, from stage 1!");
    return 666;
}).whenCompleteAsync((result, exception) -> {
    Thread.sleep(5000);
    System.out.println("Coming to you live from stage 2: " + result);
    // result is null if an error has occurred in stage 1.
    // exception is null if an error did not occur.
});

NB: If you toss this in a psv main, make sure to add a .get() at the very end; without that, the VM will exit before the future gets a shot to actually do the work. Then, you will see:

> Helloooo there, from stage 1!
> Coming to you live from stage 2: 666

The first string appears after ~5 seconds. the second after 10, and then the VM exits.


Note that it looks like java's future is not, heh, futures. Futures in java suffer from callback hell, and do not solve the 'red / blue' methods issue (that's the issue where invoking anything that (potentially) blocks from async code is a very problematic bug: It is hard to detect statically, almost impossible to test for, and nevertheless will completely ruin your performance in production. Unfortunately, it is relatively hard to realize you've accidentally done something that blocks, and few existing APIs and libraries both document whether they do or not, and then commit to never changing this without considering that change a backwards incompatible update and managing their versions appropriately to reflect this).

These are solvable problems, but it won't be easy: Java will need 'async' or similar, and also a serious effort to add documentation and possibly something that can be compile-time checked, e.g. with an annotation.

But none of that is anywhere on the horizon of java's future. What IS on the horizon, however (real soon now, timespan of a year or 2 at the most) is 'Project Loom' - which adds lightweight threads ('fibers') to java: They represent execution state but cannot, themselves, run on another core. You can make millions of em, no problem. Then you just write:

int priceyOp1 = doSomethingThatTakesLong();
int priceyOp2 = thisIsAlsoSlow(priceyOp1);

and shove the whole thing into a fiber, and even have a hopper concept where a thread pool will realize the fiber it is currently running is now blocked and go fish another fiber out of the pool and run that for a while. THat doesn't make futures completely pointless, but that does probably mean that futures will remain niche, and async/callback hell will not be solved anytime soon.

Upvotes: 3

Related Questions