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:
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. 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:
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:
Con todas estas excelentes funciones, puede que esté preguntando por los inconvenientes. Bueno, hay, por supuesto, algunos inconvenientes:
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:
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:
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.