arrayblockingqueue - blockingqueue java ejemplo
¿Cuándo debo usar SynchronousQueue? (5)
Por lo que entiendo, el código anterior hace las mismas cosas.
No, el código no es el mismo en absoluto.
Sync.Q. requiere tener camarero (s) para ofrecer para tener éxito. LBQ conservará el artículo y la oferta finalizará de inmediato, incluso si no hay camarero.
SyncQ es útil para la entrega de tareas. Imagine que tiene una lista con tareas pendientes y 3 subprocesos disponibles en espera en la cola, intente offer()
con 1/4 de la lista si no se acepta, el subproceso puede ejecutar la tarea por sí solo. [el último 1/4 debe ser manejado por el hilo actual, si te preguntas por qué 1/4 y no 1/3]
Piense en tratar de entregar la tarea a un trabajador; si no hay ninguna disponible, tiene la opción de ejecutar la tarea por su cuenta (o lanzar una excepción). Por el contrario, w / LBQ, dejar la tarea en la cola no garantiza ninguna ejecución.
Nota: el caso con los consumidores y los editores es el mismo, es decir, el editor puede bloquear y esperar a los consumidores, pero después de la offer
o de las poll
, garantiza que la tarea / el elemento sea manejado.
new SynchronousQueue()
new LinkedBlockingQueue(1)
¿Cuál es la diferencia? ¿Cuándo debo usar SynchronousQueue
contra LinkedBlockingQueue
con capacidad 1?
SynchronousQueue es más una transferencia, mientras que LinkedBlockingQueue solo permite un solo elemento. La diferencia es que la llamada put () a SynchronousQueue no se devolverá hasta que haya una llamada take () correspondiente, pero con una LinkedBlockingQueue de tamaño 1, la llamada put () (a una cola vacía) volverá inmediatamente.
No puedo decir que alguna vez haya usado SynchronousQueue directamente, pero es el BlockingQueue predeterminado que se usa para los métodos Executors.newCachedThreadPool()
. Esencialmente es la implementación de BlockingQueue para cuando realmente no quieres una cola (no quieres mantener ningún dato pendiente).
SynchronousQueue funciona de manera similar con las siguientes diferencias principales: 1) El tamaño de SynchronousQueue es 0 2) el método put () solo insertará un elemento si el método take () podrá recuperar ese elemento de la cola en el mismo momento, es decir no se puede insertar un elemento si el consumidor toma () la llamada tomará algún tiempo para consumirlo.
SynchronousQueue: insértelo solo cuando alguien lo recibirá en ese momento.
Una razón para usar SynchronousQueue es mejorar el rendimiento de la aplicación. Si debe tener una transferencia entre subprocesos, necesitará algún objeto de sincronización. Si puede satisfacer las condiciones requeridas para su uso, SynchronousQueue es el objeto de sincronización más rápido que he encontrado. Otros están de acuerdo. Ver: Implementación de BlockingQueue: ¿Cuáles son las diferencias entre SynchronousQueue y LinkedBlockingQueue?
[Solo intento ponerlo en (posiblemente) palabras más claras.]
Creo que la documentación de la API SynchronousQueue
dice las cosas muy claramente:
- Una cola de bloqueo en la que cada operación de inserción debe esperar una operación de eliminación correspondiente en otro subproceso, y viceversa.
- Una cola síncrona no tiene ninguna capacidad interna, ni siquiera una capacidad de uno. No puede mirar una cola síncrona porque un elemento solo está presente cuando intenta eliminarlo; no puedes insertar un elemento (usando ningún método) a menos que otro hilo esté tratando de eliminarlo; no se puede iterar ya que no hay nada que iterar.
- El encabezado de la cola es el elemento que el primer subproceso de inserción en cola intenta agregar a la cola; si no hay tal hilo en cola, entonces no hay ningún elemento disponible para su eliminación y
poll()
devolverá unnull
.
Y los documentos de la API de BlockingQueue
:
- Una cola que adicionalmente admite operaciones que esperan que la cola no se vacíe cuando se recupera un elemento, y espera que el espacio esté disponible en la cola cuando se almacena un elemento.
Por lo tanto, la diferencia es obvia y un tanto críticamente sutil, especialmente el tercer punto a continuación:
- Si la cola está vacía cuando está recuperando de
BlockingQueue
, el bloque de operación hasta que se inserta el nuevo elemento. Además, si la cola está llena cuando se inserta enBlockingQueue
, la operación se bloqueará hasta que el elemento se elimine de la cola y se haga un espacio para la nueva cola. Sin embargo, tenga en cuenta que enSynchronousQueue
, ya que la operación se bloquea para la operación opuesta (insertar y quitar son opuestas entre sí) para que ocurra en otro hilo. Entonces, a diferencia deBlockingQueue
, el bloqueo depende de la existencia de la operación, en lugar de la existencia o no existencia de un elemento . - Como el bloqueo depende de la existencia de una operación opuesta, el elemento nunca se inserta en la cola. Es por eso que el segundo punto: " Una cola síncrona no tiene ninguna capacidad interna, ni siquiera una capacidad de uno " .
- Como consecuencia,
peek()
siempre devuelvenull
(nuevamente, verifique el documento de la API ) yiterator()
devuelve un iterador vacío en el quehasNext()
siempre devuelvefalse
. ( Documento API ). Sin embargo, tenga en cuenta que el métodopoll()
recupera y elimina perfectamente el encabezado de esta cola, si otro subproceso está actualmente haciendo que un elemento esté disponible y si no existe tal subproceso, devuelvenull
. ( Documento API )
Finalmente, una pequeña nota, las clases SynchronousQueue
y LinkedBlockingQueue
implementan la interfaz BlockingQueue
.