30

Is there a good implementation of continuations in Java?

If so, what is the overhead like? The JVM wasn't designed with these sort of things in mind, right? So is this kind of going against the grain?

Mike
  • 58,961
  • 76
  • 175
  • 221
  • See also related http://stackoverflow.com/questions/2846428/available-coroutine-libraries-in-java – Vadzim Apr 23 '14 at 10:13
  • See also [How are coroutines implemented in JVM langs without JVM support?](https://stackoverflow.com/questions/48033944/how-are-coroutines-implemented-in-jvm-langs-without-jvm-support) – Vadzim Aug 24 '18 at 21:25

11 Answers11

13

See Apache Javaflow http://commons.apache.org/sandbox/javaflow/

It's the only continuation package for java that's actively under development. The other one, RIFE, I'm not sure which state it's in.

gawi
  • 13,940
  • 7
  • 42
  • 78
7

Jetty has continuation support. There is further discussion and some samples at DZone.

I can't advise on the efficiencies or otherwise, other than to say that the Mortbay team always appear concious of such issues. There will most likely be a discussion of implementation trade-offs somewhere on the Jetty site.

Daniel F
  • 13,684
  • 11
  • 87
  • 116
Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • 1
    It seems the Jetty continuation implementation is tied up with its Servlet container, so I don't think this can help me. – Mike Sep 22 '09 at 06:28
  • 3
    Jetty continuations are not real continuations in the programming language sense. It's just a trick to re-trigger a request processing. – gawi Sep 07 '10 at 02:16
3

Since Java 8, there is now a CompletableFuture<T> class which supports continuations and more functional / reactive programming approaches.

Consider the following example, where a Class offers a downloadAndResize method:

public CompletableFuture<Image> downloadAndResize(String imageUrl, int width, int height) {
    return CompletableFuture
        .supplyAsync(() -> downloadImage(imageUrl))
        .thenApplyAsync(x -> resizeImage(x, width, height));
}

private Image downloadImage(String url){
    // TODO Download the image from the given url...
}

private Image resizeImage(Image source, int width, int height){
    // TODO Resize the image to w / h
}

Usage of the above method could look like:

CompletableFuture<Image> imagePromise = downloadAndResize("http://some/url", 300, 200);

imagePromise.thenAccept(image -> {
    // Gets executed when the image task has successfully completed

    // do something with the image

});
IsNull
  • 676
  • 6
  • 10
  • 1
    The question asks about continuations implementations. `CompletableFuture` is just one of possible ways to nicely wrap and use them. – Vadzim Jun 13 '16 at 10:03
2

If you don't mind implicit continuations, Kilim is a great option. It works by processing annotated methods and generating the continuations in bytecode for you. Obviously it does a lot more since it's a framework, but if you want the (excellent) performance of thread-safe continuations, it's worth a look.

ngreen
  • 1,559
  • 13
  • 22
2

If I understand this correctly, I suppose the obvious problem involves unwinding the stack with closure instances active. I suppose a language with lexical scope could in theory figure out that a child frame may create a closure instance, identify those intermediate frames that are referenced, and then it could malloc those frames instead of just pushing them on the stack.

For that matter, a compiler could malloc all frames or all parent frames of a closure referencing a non-globally-bound object.

Summary

I don't think the JVM restricts closures any more than a real machine, it's just that they fight the general stack paradigm and so they usually get punted.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
1

Play! framework version 1.2.x also has support for continuations integrated with async http goodies.

Note that Play 1.2.x continuations only work with the inbuilt Netty server.

And Play 2.x still has no support for continuations.

Community
  • 1
  • 1
Vadzim
  • 24,954
  • 11
  • 143
  • 151
1

Another strong competitior has appeared recently.

Quasar uses forked from Matthias Mann's implementation of java continuations to provide higher level features like lightweight threads, Erlang-like actors and Go-like coroutines and channels.

There are many benchmarks and detailed introductions in the Quasar Blog.

There is also ready-to-use integration named Comsat aimed to help easily building performant web services based on continuations machinery under the hood.

Quasar also provides a nice Kotlin API that was featured on recent JetBrains webinar Quasar: Efficient and Elegant Fibers, Channels and Actors.

Everything mentioned is open-source and free to use.

See also http://blog.paralleluniverse.co/2015/08/07/scoped-continuations/


Update

Quasar's experience was later used as foundation for the Loom Project which aims to bring continuations support directly into JVM sometime past Java 11.

It's under active development now and already has a working alpha prototype.

Vadzim
  • 24,954
  • 11
  • 143
  • 151
1

Consider also Kotlin Coroutines.

It's implemented via potentially more performant CPS transformations (still stackful) and can use any async executor under the hood like ForkJoinPool or Quasar integration.

Comes with handy guided library.

Beware of some tooling and reflection pitfalls.

Vadzim
  • 24,954
  • 11
  • 143
  • 151
0

Scala also runs on JVM. So it might be relevant.

What are Scala continuations and why use them?

In addition Scala has somewhat similar async/await feature:

http://docs.scala-lang.org/sips/pending/async.html

Community
  • 1
  • 1
Vadzim
  • 24,954
  • 11
  • 143
  • 151
0

Another library by Matthias Mann:

http://www.matthiasmann.de/content/view/24/26/

http://www.matthiasmann.de/java/Continuations/

Vadzim
  • 24,954
  • 11
  • 143
  • 151
  • A fork of this proof-of-concept library was used in much more feature-rich and mature [Quasar](http://stackoverflow.com/a/37789961/603516) framework. – Vadzim Jun 13 '16 at 12:36