Bibliotecas Coroutine disponibles en Java

Me gustaría hacer algunas cosas en Java que serían más claras si se escriben usando rutinas concurrentes, pero para las que los hilos completos son excesivos. La respuesta, por supuesto, es el uso de corrutinas , pero no parece haber ningún soporte de corotine en las bibliotecas estándar de Java y un rápido Google en él trae sugerencia tentadora aquí o allá, pero nada sustancial.

Esto es lo que he encontrado hasta ahora:

  • JSIM tiene una clase de corrutina, pero parece bastante pesada y se confunde, aparentemente, con hilos en los puntos. El objective de esto es reducir la complejidad del enhebrado completo, no agregarlo. Además, no estoy seguro de que la clase se pueda extraer de la biblioteca y usar de forma independiente.
  • Xalan tiene una clase de juego de corrutinas que hace cosas parecidas a la corutina, pero de nuevo es dudoso si esto se puede extraer de manera significativa de la biblioteca general. También parece que está implementado como una forma estrechamente controlada de grupo de subprocesos, no como corutinas reales.
  • Hay un proyecto de Google Code que se parece a lo que busco, pero en todo caso parece más pesado que usar hilos. Básicamente estoy nervioso de algo que requiere software para cambiar dinámicamente el bytecode de JVM en tiempo de ejecución para hacer su trabajo. Esto parece excesivo y como algo que causará más problemas de los que las corutinas resolverían. Además, parece que no implementa todo el concepto de coroutine. Con solo echar un vistazo, da una característica de yield que simplemente regresa al invocador. Las corutinas adecuadas permiten que los yield transfieran el control a cualquier corrutina conocida directamente. Básicamente, esta biblioteca, tan pesada y aterradora como es, solo te brinda soporte para iteradores, no para corotines completamente generales.
  • El Corutine for Java, que tiene un nombre prometedor, falla porque es una solución específica de la plataforma (obviamente usando JNI).

Y eso es todo lo que he encontrado.

Conozco el soporte de JVM nativo para corutinas en la máquina Da Vinci y también sé sobre el truco de continuación de JNI para hacer esto. Sin embargo, estas no son realmente buenas soluciones para mí, ya que no necesariamente tendría control sobre qué VM o plataforma se ejecutaría mi código. (De hecho, cualquier sistema de manipulación de bytecode sufriría problemas similares, sería mejor si fuera Java puro, si es posible. La manipulación del bytecode en tiempo de ejecución me restringiría el uso de esto en Android, por ejemplo).

Entonces, ¿alguien tiene alguna indicación? ¿Esto es posible? Si no, ¿será posible en Java 7?


Editado para agregar:

Solo para asegurar que se contenga la confusión, esta es una pregunta relacionada a la otra , pero no es lo mismo. Éste busca una implementación existente en una apuesta para evitar reinventar la rueda innecesariamente. El otro es una pregunta sobre cómo se implementaría corutinas en Java si esta pregunta resultara imposible de responder. La intención es mantener diferentes preguntas sobre diferentes hilos.


Editado adicionalmente para agregar:

La respuesta está seleccionada . Algunos comentarios, sin embargo, están en orden. La biblioteca señalada no es una biblioteca de corrutinas, por lo que técnicamente no responde mi pregunta. Dicho esto, sin embargo, tiene dos bordes sobre el proyecto de Google Code vinculado anteriormente:

  1. Ambas soluciones utilizan la manipulación de bytecode, pero la biblioteca seleccionada permite la manipulación de bytecode estático que lo hace utilizable en Android y otras stacks de JVM no compatibles.
  2. El proyecto de Google Code no hace corrutinas completas. Si bien la biblioteca de la respuesta ni siquiera tiene corotines, hace algo más importante: proporciona una buena herramienta fundamental para desplegar mis propias corutinas con todas las funciones.

Javaflow es una implementación de continuación, probablemente le permita hacer eso. Sin embargo, utiliza la manipulación de bytecode.

De todos modos, parece que estás tratando de hacer OOP con C. simple. Es posible, pero no significa que debas hacerlo.

El marco de Kilim implementa corutinas mediante el uso de reescritura de código de bytes. Lo he usado yo mismo para implementar procesos ligeros en Erjang , y es muy estable y sorprendentemente rápido para la cantidad de reescritura de códigos de bytes que continúa.

Las corutinas de Kilim interactúan mediante el uso de buzones, por lo que utilizo el marco para modelar actores de Erlang. Pero también puede usarse para hacer corutinas en un modelo de memoria compartida.

¿Qué piensas de esta biblioteca de continuación escrita por Matthias Mann? He copiado los pros y los contras del sitio web del creador para facilitar la discusión. Es importante mirar las pruebas en el código fuente para ver más allá del único ejemplo en el sitio web.

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

Comencemos con lo que obtienes:

  • Escriba código secuencial simple: ya no necesita crear máquinas de estado a mano
  • No se crean o necesitan subprocesos, no hay problemas de sincronización de subprocesos múltiples
  • No hay creación de basura desde la ejecución del código
  • Muy breve tiempo de ejecución
  • Solo se cambian las llamadas a métodos suspendibles: todas las llamadas a su biblioteca estándar (como java.util. * Etc.) no se ven afectadas en absoluto.
  • Soporte completo de serialización
  • Puede almacenar el estado de ejecución de corutinas como parte del estado de su juego en su juego de salvar sin ningún código adicional. Esto, por supuesto, requiere que sus clases y tipos de datos que utilice en sus corrutinas sean serializables. Soporte completo para manejo de excepciones y finalmente bloques
  • El preprocesamiento sin conexión no ralentiza el tiempo de carga de la aplicación. Por supuesto, la instrumentación del tiempo de ejecución también es posible.
  • Biblioteca de tiempo de ejecución muy pequeña: menos de 10 KByte (JAR sin comprimir) Licencia BSD

Con todas estas excelentes funciones, puede que esté preguntando por los inconvenientes. Bueno, hay, por supuesto, algunos inconvenientes:

  • Los constructores y los inicializadores estáticos no se pueden suspender
  • Los métodos suspendibles no se pueden sincronizar ni tienen bloques sincronizados
  • Debe descargar la biblioteca ASM3 para ejecutar la tarea de instrumentación
  • No puedes llamar al método suspendible con reflexión

El problema de la sincronización se puede solucionar poniendo código que requiere el uso de la sincronización en su propio método.

Sus requisitos parecen ser:

  • liviano: no basado en hilos,
  • no confiar en el código nativo, y
  • no se usa la modificación del código de bytes.

Tengo la desagradable sensación de que estos requisitos han descartado todas las estrategias sensatas para implementar coroutines en Java.

Play framework ahora proporciona continuaciones con Javaflow. Debido a que Play proporciona tanta comodidad en otras áreas, es posible que desee comenzar con esto.

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

Si está utilizando Java, hay 2 opciones disponibles a partir de finales de 2017:

  • Corutinas
  • Tasclate-Javaflow

Ambas están basadas en commons -javaflow- y vuelven a escribir su código en el nivel de bytecode para que las cosas funcionen.

Mantengo las Corutinas : los aspectos positivos son que es rápido, es compatible con todos los principales sistemas de comstackción y admite la serialización / control de versiones de tus corrutinas. El lado negativo es que la API tiene algunas desviaciones de los comunes-javaflow.

Vsilaev mantiene Tasclate-Javaflow : no lo he usado, así que no puedo hablar sobre él, pero se mantiene y, al observar los ejemplos, su API se aproxima más a la de commons-javaflow.

También hay funciones de lenguaje en Kotlin y Scala (y quizás otros lenguajes basados ​​en JVM) que le permiten usar corutinas. Pero, antes de cambiar de idioma, debe tener en cuenta que Kotlin, Scala o el lenguaje JVM du jour de hoy no es ni nunca será Java. Lo que sea que esté haciendo en segundo plano para hacer que las cosas funcionen, puede que no funcione cuando llegue el próximo lanzamiento de la JVM.

Las personas que mantienen el JDK en Oracle tienen un historial de uso de estos lenguajes JVM de terceros como estudios de mercado. Si se agrega una característica de alto nivel a un lenguaje JVM de un tercero y es lo suficientemente popular, lo incorporará en Java. Esto es lo que está sucediendo ahora con corrutinas. Hay un proyecto OpenJDK llamado Project Loom que tiene como objective agregar corutinas al lenguaje Java.

Todavía es temprano para el Proyecto Loom. Si analizas críticamente la propuesta, es un desastre. Estoy seguro de que se estabilizará a medida que pasa el tiempo, pero lo que finalmente terminaremos puede ser completamente diferente de lo que muchos de nosotros esperamos.

Para recapitular, sus opciones son utilizar uno de los kits de herramientas de instrumentación de código de bytes o cambiar de idioma. Project Loom todavía está en los primeros días y existe la posibilidad de que nunca se agregue realmente a Java.

Quasar implementa corotines y canales similares a Go entre otras características utilizando continuaciones.

Más detalles, puntos de referencia y enlaces en Quasar en mi otra respuesta .

Revisé la pregunta relacionada que vinculó y, por mi vida, no puedo entender realmente qué tienen de malo los hilos. En Java, los hilos nunca son hilos nativos, simplemente son unidades de ejecución aisladas que, dependiendo del contexto, se pueden ejecutar como su propio hilo nativo si es beneficioso, es decir, dividir grandes bloques de ejecución entre los hilos propios es inteligente y mantener los pequeños en unos pocos es más sensato debido a la sobrecarga.

Dicho esto, Java / JDK no tiene nativamente corutinas disponibles para los progtwigdores de alto nivel, aún. JDK7 ( siempre que eso salga ) tendrá lo que se conoce como jsr166y que es un armazón Fork / Join de Doug Lea. Para obtener información técnica, consulte este PDF por mr. Lea mismo. En la práctica, Fork / Join agrega otro nivel de granularidad ( ¡útil! ) Sobre el modelo de subprocesamiento interno de Java, que debería ayudarlo a lograr lo que desea.