Java中可用的协程库

时间:2010-05-17 03:03:16

标签: java coroutine

我想用Java做一些事情,如果使用并发例程编写会更清楚,但对于哪些完整线程严重过度杀伤。当然,答案是coroutines的使用,但标准Java库中似乎没有任何协程支持,快速的谷歌在这里或那里带来诱人的提示,但没有实质性的。

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

  • JSIM有一个协程类,但它看起来非常重量级,并且似乎与  点上的线程。这样做的目的是降低全面线程的复杂性,而不是增加  它。此外,我不确定该类是否可以从库中提取并独立使用。
  • Xalan有一个协程集类,可以执行类似协同程序的东西,但是如果这样的话,那也是可疑的  可以从整个库中有意义地提取。它看起来像是作为一个实现  严格控制的线程池形式,而不是实际的协程。
  • 有一个Google Code project看起来就像我追求的那样,但如果有什么看起来更像  重量级比使用线程更重要。我基本上对需要软件的东西感到紧张  在运行时动态更改JVM字节码以完成其工作。这看起来像矫枉过正等  一些会导致比协同程序解决的问题更多的问题。此外,它看起来没有  实现整个协程概念。通过我的一瞥,它提供了一个只返回的yield功能  对调用者。正确的协同程序允许yield直接将控制权转移到任何已知的协程。  基本上这个库,重量级和可怕的,只给你支持迭代器,而不是  完全一般的协程。
  • 有希望命名的Coroutine for Java失败,因为它是特定于平台的(显然是使用  JNI)解决方案。

这就是我找到的所有内容。

我知道Da Vinci Machine中对协同程序的本机JVM支持,我也知道JNI continuations trick这样做。但是,对我来说这些并不是一个很好的解决方案,因为我不一定能控制我的代码运行在哪个VM或平台上。 (事实上​​,任何字节码操作系统都会遇到类似的问题 - 如果可能的话,最好是纯Java。运行时字节码操作会限制我在Android上使用它。)

那么有人有任何指针吗?这甚至可能吗?如果没有,是否可以在Java 7中使用?


已编辑添加:

为了确保包含混淆,这是my other one相关问题,但不一样。这是为了避免不必要地重新发明轮子,正在寻找现有的实施方案。另一个是关于如何在Java中实现协程的问题,如果这个问题无法解决的话。目的是在不同的线程上保留不同的问题。


进一步编辑添加:

answer is selected。然而,有些评论是有条理的。图书馆指出的不是一个协程库,所以它在技术上不回答我的问题。尽管如此,它与上面链接的Google Code项目有两个优势:

  1. 两种解决方案都使用字节码操作,但所选的库允许静态字节码操作,这使得它可以在Android和其他不兼容的JVM堆栈中使用。
  2. Google Code项目不执行完整协同程序。虽然答案的库甚至根本不做协同程序,但它做了更重要的事情:它提供了一个很好的基础工具来滚动我自己的全功能协程。

9 个答案:

答案 0 :(得分:12)

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

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

答案 1 :(得分:10)

Kilim框架通过使用字节码重写来实现协同程序。我自己使用它来实现Erjang中的轻量级进程,并且它非常稳定,并且对于正在进行的字节码重写量来说非常快。

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

答案 2 :(得分:9)

您如何看待Matthias Mann撰写的这个延续库?我复制了创作者网站的优点和缺点,以方便讨论。重要的是要查看源代码中的测试,以查看网站上的一个示例。

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

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

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

拥有所有这些强大的功能 - 你可能会要求它们的缺点。那么当然有一些缺点:

  • 无法暂停构造函数和静态初始值设定项
  • 暂停方法无法同步或具有同步块
  • 您需要下载ASM3库才能运行检测任务
  • 您不能使用反射调用可挂起的方法

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

答案 3 :(得分:5)

您的要求似乎是:

  • 轻量级 - 不基于线程,
  • 不依赖本机代码,
  • 不使用字节码修改。

我有一种令人讨厌的感觉,这些要求排除了在Java中实现协同程序的所有合理策略。

答案 4 :(得分:3)

如果你正在使用Java,截至2017年底有两种选择:

这两个都基于commons-javaflow - 他们在字节码级重新编写代码以使事情发挥作用。

我保持Coroutines - 前端是它快速,它支持所有主要的构建系统,并且它支持你的协同程序的序列化/版本控制。缺点是API与commons-javaflow存在一些偏差。

Vsilaev坚持Tasclate-Javaflow - 我还没有使用它,所以我无法发表意见,但它得到了维护,并且通过查看示例,它的API更接近于commons-javaflow。

Kotlin和Scala(以及其他基于JVM的语言)中还有一些语言功能可以让你使用协同程序。但是,在切换语言之前,你应该意识到Kotlin,Scala或者JVM语言今天的任何东西都不是,也永远不会是Java。无论它在后台做什么以使事情有效都可能在JVM的下一个版本推出时无效。

在Oracle维护JDK的人有将这些第三方JVM语言用作市场研究的记录。如果将高级功能添加到第三方JVM语言并且它非常流行,他们会将其合并到Java中。这就是协同程序现在正在发生的事情。这是一个名为Project Loom的OpenJDK项目,旨在将协程添加到Java语言中。

Project Loom还处于早期阶段。如果你批判性地审视提案,那就太乱了。我确信它会随着时间的推移而稳定下来,但我们最终会得到的结果可能与我们许多人期待的完全不同。

总结一下,您可以选择使用其中一个字节码检测工具包或切换语言。 Project Loom仍处于早期阶段,可能永远不会被添加到Java中。

答案 5 :(得分:2)

Play框架现在提供Javaflow的延续。因为Play在其他方面提供了很多便利,所以你可能想要从它开始。

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

答案 6 :(得分:1)

有一个适用于Java的新的协程框架库。它是用纯Java实现的,因此不需要单独运行JNI或Java代理。它是开源的,可以从GitHub下载:

https://github.com/esoco/coroutines

可在Medium上找到该框架的简介

https://medium.com/@esocogmbh/65661a379c85

答案 7 :(得分:0)

Quasar使用continuation实现Go-like coroutines和其他功能之间的通道。

我的another answer中有关Quasar的更多详细信息,基准和链接。

答案 8 :(得分:-2)

我检查了你链接的相关问题,对于我的生活,我无法真正理解线程的坏处。在Java线程中,永远不是本机线程,它们只是孤立的执行单元,根据上下文可能作为自己的本机线程运行,如果它是有益的,那就是将大型执行块拆分为自己的线程是聪明的,同时将小型执行块保留在少数几个因开销而更加明智。

也就是说,Java / JDK本身并没有为高级程序员提供协同程序。 JDK7(何时出现)将具有所谓的jsr166y,这是Doug Lea的Fork / Join框架。有关技术信息,请{先生check this PDF先生。莉亚本人。在实践中,Fork / Join在Java的内部线程模型之上添加了另一个(有用的!)粒度级别,这可以帮助您实现所需的目标。