Equivalente de Goroutines en Clojure/Java
concurrency (8)
Hace poco disfruté viendo la charla de Google IO sobre los patrones de Go Concurrency
Aunque el enfoque de ir a la concurrencia (grutinas, comunicación por canales) es claramente diferente de Clojure (inmutabilidad, referencias gestionadas, STM), parecía que el enfoque de Go podría ser útil en algunas circunstancias en un contexto de Clojure.
Entonces, ¿existe un equivalente directo en Clojure o Java para las primitivas de concurrencia de Go (tal vez una biblioteca), en particular:
- objetos tipo
channel
que se bloquean hasta que haya un lector y un escritor disponibles en ambos extremos - Una construcción tipo
select
que puede esperar resultados en múltiples canales
PD Perfectamente satisfecho con una solución Java, ya que sería fácil de usar desde Clojure
ACTUALIZACIÓN Dado que la pregunta se realizó originalmente, Clojure ahora tiene core.async que proporciona todas estas funciones y más.
Eche un vistazo a Joxa . Es un dialecto tipo Clojure de Lisp dirigido a la Máquina Virtual Erlang.
Y Erlang es conocido por procesos livianos de menos de 1000 bytes.
También Erjang está relacionado de alguna manera y podría interesarte. Es una implementación de Erlang Virtual Machine en la parte superior de JVM.
Entonces teóricamente puedes compilar Joxa a BEAM y luego aún ejecutarlo en JVM. No es que lo recomiende :-).
Sin saber nada sobre Go, eche un vistazo a Lamina para ver si se ajusta a lo que está buscando https://github.com/ztellman/lamina
objetos similares a canales que bloquean hasta que haya un lector y un escritor disponibles en ambos extremos
Esto es un poco confuso ¿Quiere decir "bloques hasta que, si está escrito, hay un lector disponible o, si está leyendo, hay un escritor disponible"? Estoy hablando en nombre de los hilos y no de la construcción, una construcción no puede bloquear solo los hilos. (Para evitar confusiones, una construcción instruiría a los hilos para que bloqueen).
Si mi suposición es cierta, hay dos opciones que puede tener (en Java estándar).
- SynchronousQueue
- TransferQueue (aunque esto también puede usarse como un canal de almacenamiento intermedio)
Una construcción tipo selección que puede esperar resultados en múltiples canales
Por lo que yo sé, no hay ningún verdadero tipo de construcciones similares. Lo más cercano que puede tener es un ExecutionCompletionService que se devolverá cuando se complete la siguiente tarea disponible presentada.
el actor akka ~ = canal goroutine +
Recomiendo JCSP , basado en los algoritmos Occam / transputer. Las partes clave de esta implementación API se han comprobado con precisión mediante métodos formales y algoritmos formales de prueba, por lo que son lo más confiables posible (la clase alternativa es el principal logro en este sentido).
JCSP es muy bueno ... sin embargo, la desventaja sigue siendo las limitaciones impuestas por la JVM, especialmente el alto costo de los hilos. En Go u Occam, los hilos se pueden contar en millones, pero no en la JVM.
Recientemente escribí ligeramente , una biblioteca de Clojure para apoyar la programación con construcciones de concurrencia de Go, poniendo algunos modismos de Clojure en ese estilo de programación concurrente.
Los constructos principales de la programación de concurrencia de Go son:
- Ir rutinas
- Canales sincrónicos (de bloqueo)
- Canales delimitados, en su mayoría asincrónicos (sin bloqueo)
- Un operador de
select
que lee el siguiente mensaje disponible de múltiples canales - Las operaciones de tiempo de espera en el canal leen / escriben / seleccionan
La biblioteca go-lightly tiene todas estas características, basándose en las características disponibles en Java y Clojure. Las rutinas True Go se multiplexan en subprocesos, en lugar de utilizar completamente un subproceso durante toda su vida útil. A la ligera, construyo rutinas sobre la macro futuro de Clojure, por lo que esta es la parte más débil del modelo Go en la JVM.
Intenté usar lámina, pero carece de canales delimitados (lo que podría querer en algunos escenarios y es parte del modelo de canal con búfer Go) y, por lo que puedo ver, carece de una manera de tener un bloque de productor al colocar un mensaje en un canal. Esa es una característica crucial del modelo de concurrencia Go.
He incluido varios ejemplos usando la biblioteca ir-lightly en el git repo. La mayoría se basan en ejemplos que Rob Pike ha dado en conversaciones en los últimos dos años.
Sería interesante construir una biblioteca Clojure sobre JCSP, pero aún no investigué.
Es posible que desee ver Quasar / Pulsar . Es muy nuevo, pero es exactamente lo que estás buscando.
Debería verificar core.async . Es una biblioteca escrita por Rich Hickey que implementa canales de estilo go.