Ir al canal vs Java BlockingQueue

¿Hay alguna diferencia entre un canal Go y un BlockingQueue de Java? Ambas son colas con bloqueo y semántica de modelo de memoria similares. Opcionalmente ambos pueden tener un conjunto de capacidad.

preguntado el 21 de mayo de 12 a las 19:05

4 Respuestas

Yo diría que la mayor diferencia es que los canales Go tienen soporte para el select declaración, que le permiten realizar exactamente una operación de canal. Un ejemplo (alterado del Ir a la especificación de idioma):

select {
case i1 = <-c1:
    print("received ", i1, " from c1\n")
case c2 <- i2:
    print("sent ", i2, " to c2\n")
case i3, ok := (<-c3):  // same as: i3, ok := <-c3
    if ok {
        print("received ", i3, " from c3\n")
    } else {
        print("c3 is closed\n")
    }
}

En este ejemplo, se realizará exactamente una de las operaciones recibir de c1, enviar a c2 o recibir de c3. Al ingresar la selección, se selecciona aleatoriamente un canal listo (si lo hay). De lo contrario, la operación se bloquea hasta que uno de los canales esté listo.

No conozco ninguna forma trivial de modelar esta selección de canales utilizando las utilidades de Java. Se podría argumentar que esta es una propiedad de la select declaración en lugar del diseño de los canales, pero diría que es fundamental para el diseño de los canales.

contestado el 21 de mayo de 12 a las 23:05

Creo que podría acercarse usando el método de encuesta en una cola de bloqueo. Pero tiene razón en que la declaración de selección brinda soporte sintáctico para la multiplexación en varios canales diferentes. - Jeremy Wall

Correcto, no mencioné la espera ocupada porque considero que no es una solución :-). - brett kail

Otra diferencia muy importante es: puede cerrar un canal Go para indicar que no vienen más elementos. Eso no es posible usando Java.

Ejemplo: goroutine A lee una lista de archivos. Publica cada archivo en el canal. Después del último archivo, cierra el canal. goroutine B lee los archivos del canal y los procesa de alguna manera. Después de que se cierra el canal, la gorutina se cierra.

Hacer esto en Java no es posible fácilmente; sin embargo, existen algunas soluciones.

Respondido el 21 de Septiembre de 13 a las 20:09

¡Por supuesto! Esta es una diferencia muy importante. Con Java, debe enviar algún tipo de registro dudoso o carácter de final de flujo para indicar que no se reciben más elementos. Esto requiere código adicional en ambos lados, consulte javadoc de BlockingQueue: a common tactic is for producers to insert special end-of-stream or poison objects, that are interpreted accordingly when taken by consumers. - Mahmud Ben Hassine

¿Alguien sabe por qué BQ no se implementó cerca? Parece algo simple pero útil y esencial - Serguéi Ponomarev

Se pueden usar de manera similar.

  • Ambos pueden bloquearse al poner/enviar o al tomar/recibir.
  • Ambos tienen una capacidad que rige cuando se bloqueará el envío.

Las mayores diferencias son probablemente que los canales go son considerablemente más baratos que un objeto java. y que los canales go se pueden restringir para que solo envíen o solo reciban, lo que puede garantizar algún tipo de cumplimiento adicional con respecto a quién puede enviar y quién puede recibir de un canal.

contestado el 21 de mayo de 12 a las 20:05

¿Tiene fuente para demostrar que son mucho más baratos? No es que no te crea, pero no me sorprendería que algunas de las colas de Java y los canales nio pudieran mantenerse al día en términos de tiempo de ejecución. Sin embargo, estoy seguro de que Java pierde en el frente de la memoria. - adam caballero

@AdamGent Me temo que no tengo ninguna fuente disponible. Sin embargo, estaba hablando principalmente de la memoria, no de la velocidad de ejecución. - Jeremy Wall

Para hacer algo similar a la instrucción golang'select en java, se necesitaría usar el paquete java.nio. Concretamente selectores y canales. Consulte los documentos del paquete aquí:

http://docs.oracle.com/javase/6/docs/api/java/nio/channels/package-summary.html#multiplex

Ofrece prácticamente la misma capacidad que la declaración de selección de golang, utilizando un solo hilo para multiplexar lectura/escritura desde múltiples canales.

Respondido el 10 de Septiembre de 13 a las 16:09

Los canales Go permiten la transferencia de estructuras de datos arbitrarias (incluidos los punteros), pero java.nio.channels solo permite la transferencia de bytes. No creo que sean realmente comparables. - brett kail

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.