Java中可用的协程库

我想在Java中做一些东西,如果使用并发例程编写的话会更清楚,但是对于哪些完整的线程严重矫枉过正。 答案当然是使用协同程序 ,但在标准的Java库中似乎没有任何协程支持,并且它上面的一个快速的Google带来了诱人的提示,但没有任何实质性的提示。

这是我到目前为止发现的:

  • JSIM有一个协程类,但它看起来相当重量级,似乎与线程的点。 这一点是为了减less全线程的复杂性,而不是增加它。 此外,我不确定该类可以从库中提取和独立使用。
  • Xalan有一个协程类集,它可以做类似协程的东西,但是如果能从整个图书馆中有意义地抽取出来的话,这个问题也是可疑的。 它看起来像是作为线程池的严格控制forms实现的,而不是实际的协程。
  • 有一个谷歌代码项目 ,看起来像我之后,但如果有什么看起来比使用线程更重量级。 我基本上很紧张,需要软件在运行时dynamic地改变JVM字节码来完成它的工作。 这看起来像是矫枉过正,就像一些会比协同程序解决更多问题的东西。 而且看起来它并没有实现整个协程的概念。 通过我的浏览,它提供了一个返回给调用者的yield特性。 正确的协程允许yields直接将控制转移到任何已知的协程。 基本上这个库,重量级和可怕的,只是给你支持迭代器,而不是完全一般的协程。
  • 这个名为Coroutine的Java失败了,因为它是一个特定于平台(显然使用JNI)的解决scheme。

这就是我发现的一切。

我知道Da Vinci机器上的原生JVM对协程的支持,我也知道JNI的延续技巧 。 但是,这些对我来说并不是很好的解决scheme,因为我不一定能控制我的代码运行在哪个虚拟机或平台上。 (事实上​​,任何字节码操作系统都会遇到类似的问题 – 如果可能的话,最好是纯Java。运行时字节码操作会限制我在Android上使用它)。

那么有没有人有指点? 这甚至有可能吗? 如果没有,Java 7中可能吗?


编辑添加:

只是为了确保混淆,这是我的另一个 相关问题,但不是相同的。 这是寻求一个现有的实施,以避免不必要的重新发明车轮。 另一个是关于如何在Java中执行协程的问题,如果这个问题certificate是无法回答的话。 目的是在不同的线程上保留不同的问题。


进一步编辑添加:

答案被选中 。 但是,一些评论是为了。 图书馆指出不是一个协同程序库,所以它在技术上不能回答我的问题。 这就是说,但它有两个优势链接到上面的Google Code项目:

  1. 两种解决scheme都使用字节码操作,但所选库允许静态字节码操作,这使得它可用于Android和其他不兼容的JVM堆栈。
  2. Google Code项目不会执行完整的协程。 虽然答案的库甚至不做协程,但是它更重要:它为我自己的全function协程提供了一个很好的基础工具。

Javaflow是一个继续实现,它可能会让你这样做。 它使用字节码操作。

无论如何,感觉就像你用普通的C做OOP一样。这是可行的,但这并不意味着你应该这样做。

Kilim框架通过使用字节码重写来实现协程。 我自己用它来实现Erjang中的轻量级进程,而且对于字节码重写的数量来说 ,它是非常稳定和令人惊讶的快速的。

Kilim的协同程序通过使用邮箱进行交互,所以我使用框架来模拟Erlang参与者。 但是它也可以用于在共享内存模型中进行协同程序。

你如何看待Matthias Mann写的这个延续库? 我抄袭了创作者网站的优点和缺点,以便于讨论。 查看源代码中的testing以查看网站上的一个示例是非常重要的。

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

让我们从你得到的东西开始:

  • 编写简单的顺序代码 – 您不再需要手动创build状态机
  • 没有线程创build或需要 – 没有multithreading同步问题
  • 从代码执行没有垃圾创build
  • 很小的运行时间开销
  • 只有可挂起的方法调用才会改变 – 所有对标准库的调用(如java.util。*等)都不受影响。
  • 全面的序列化支持
  • 您可以将协程的执行状态作为游戏状态的一部分存储在保存游戏中,而无需任何其他代码。 这当然要求你在你的协同程序中使用的类和数据types是可序列化的。 完全支持exception处理,并最终阻止
  • 离线预处理不会减慢您的应用程序加载时间当然,运行时检测也是可能的。
  • 非常小的运行时库 – less于10 KB(未压缩的JAR)BSD许可证

拥有所有这些优点 – 你可能会要求这些缺点。 那当然有一些缺点:

  • 构造函数和静态初始化程序不能被挂起
  • 可挂起的方法不能同步或有同步块
  • 您需要下载ASM3库以运行检测任务
  • 您无法使用reflection调用可挂起的方法

同步问题可以通过将需要使用同步的代码放入自己的方法来解决。

您的要求似乎是:

  • 轻量级 – 不基于线程,
  • 不依赖本地代码,并且
  • 没有使用字节码修改。

我有一个肮脏的感觉,这些要求已经排除了在Java中执行协程的所有明智的策略。

Play框架现在提供了Javaflow的延续。 由于Play在其他方面提供了很多的便利,所以您可能需要先从它开始。

http://www.playframework.org/documentation/1.2RC2/releasenotes-1.2#Continuations

类星体使用延续实现Go-like协同程序和其他function。

更多的细节,基准和链接在我的另一个答案的类星体。

我检查了你链接的相关问题,对于我的生活,我无法真正理解线程的坏处。 在Java中,线程永远不是本地线程,它们只是一个独立的执行单元,根据上下文的不同,它们可以作为自己的本地线程运行(如果有益的话),那就是将大的执行块分割成自己的线程是聪明的,由于开销而更明智。

也就是说,Java / JDK本身并不具备可供高级程序员使用的协程。 JDK7( 无论什么时候出现 )都会有Doug Lea提供的Fork / Join框架jsr166y 。 有关技术信息, 请先阅读此PDF 。 Lea自己。 在实践中,Fork / Join在Java的内部线程模型之上增加了另一个( 有用的 )粒度级别,这应该可以帮助你实现你想要的。