Pregunta

Tengo una cola de bloqueo de los objetos.

Quiero escribir un hilo que bloquea hasta que hay un objeto en la cola. Similar a la funcionalidad proporcionada por BlockingQueue.take ().

Sin embargo, ya no sé si seré capaz de procesar el objeto de éxito, quiero simplemente PEEK () y no extraer el objeto. Quiero eliminar el objeto sólo si soy capaz de procesar con éxito.

Por lo tanto, me gustaría una función de bloqueo peek (). Actualmente, ojeada () sólo devuelve si la cola está vacía según las javadocs.

Me estoy perdiendo algo? ¿Hay otra manera de conseguir esta funcionalidad?

EDIT:

¿Alguna idea sobre si acabo de utilizar una cola segura hilo y asomé y dormía en su lugar?

public void run() {
    while (!exit) {
        while (queue.size() != 0) {
            Object o =  queue.peek();
            if (o != null) {
                if (consume(o) == true) {
                    queue.remove();
                } else {
                    Thread.sleep(10000); //need to backoff (60s) and try again
                }
            }
        }
        Thread.sleep(1000); //wait 1s for object on queue
    }
}

Nota que sólo tengo un hilo consumidor y uno (separado) hilo productor. Supongo que esto no es tan eficiente como el uso de un BlockingQueue ... Cualquier comentario apreciados.

¿Fue útil?

Solución

Se puede usar un LinkedBlockingDeque y retirar físicamente el elemento de la cola (utilizando takeLast()), pero reemplazarlo de nuevo en al final de la cola si el procesamiento falla usando putLast(E e). Mientras tanto los "productores" podrían añadir elementos a la frontal de la uso de putFirst(E e) cola.

Siempre se puede encapsular este comportamiento dentro de su propia implementación Queue y proporcionar un método que realiza blockingPeek() takeLast() seguido por putLast() detrás de las escenas en el LinkedBlockingDeque subyacente. Por lo tanto, desde la perspectiva del cliente que llama el elemento no se elimina de la cola.

Otros consejos

  

Sin embargo, ya no sé si seré capaz de procesar el objeto de éxito, quiero simplemente PEEK () y no extraer el objeto. Quiero eliminar el objeto sólo si soy capaz de procesar con éxito.

En general, no es seguro para subprocesos. ¿Y si, después de peek() y determinar que el objeto puede ser procesado con éxito, pero antes de que take() para eliminar y procesar, otro hilo detiene objeto?

Lo único que soy consciente de que no se trata de BlockingBuffer en Apache Commons Colecciones :

  

Si bien obtener o eliminar se llama en   un búfer vacío, el subproceso de llamada   espera a que la notificación de que un complemento o   addAll operación se ha completado.

get() es equivalente a peek(), y una Buffer puede ser hecho para actuar como BlockingQueue mediante la decoración de un UnboundedFifoBuffer con un BlockingBuffer

Podría también acaba de añadir una cola de detector de eventos a la cola de bloqueo, a continuación, cuando se añade algo a la cola (bloqueo), enviar un evento fuera de sus oyentes? Usted podría tener su secuencia de rosca hasta que se fue llamado método actionPerformed.

La respuesta rápida es decir, no existe en realidad no es una manera de tener un vistazo de bloqueo, barra de la aplicación de una cola de bloqueo con una mirada de bloqueo () usted mismo.

  

Me estoy perdiendo algo?

peek () puede ser problemático con concurrencia -

  • Si no puede procesar su peek () 'd mensaje -. Va a ser dejado en la cola, a menos que tenga múltiples consumidores
  • ¿Quién va a conseguir que el objeto fuera de la cola si no puede procesarlo?
  • Si tiene varios consumidores, se obtiene una condición de carrera entre usted PEEK () 'ing y otro hilo también el tratamiento de partidas, lo que resulta en el procesamiento duplicado o peor.

Parece que usted puede ser mejor eliminación de hecho el elemento y procesarla mediante una patrón de Cadena de responsabilidad

Editar: re: el último ejemplo: Si sólo 1 de los consumidores, que nunca deshacerse del objeto en la cola - a menos que se actualiza en la media hora - en cuyo caso es mejor que ser muy cuidadoso acerca hilo de seguridad y probablemente no debería haber puesto el elemento en la cola de todos modos.

Parece que sí BlockingQueue no tiene la funcionalidad que está especificando.

Yo podría tratar de volver a enmarcar el problema un poco sin embargo: ¿Qué haría con los objetos no se puede "procesar correctamente"? Si acaba de dejarlos en la cola, que tendrá que tirar de ellos en algún momento y tratar con ellos. Yo recomiendo cualquiera de encontrar la manera de procesarlos (comúnmente, si un queue.get () da ningún tipo de valor no válido o malo, es probable que estés bien apenas caer en el suelo) o la elección de una estructura de datos diferente a un FIFO.

No es una respuesta en sí, sino: JDK-6653412 afirma que esta no es un caso de uso válido.

La solución 'simple'

  

No procesar la siguiente hasta que el elemento de anterior elemento se procesa con éxito.

public void run() {

Object lastSuccessfullyProcessedElement = null;

    while (!exit) {
        Object obj =  lastSuccessfullyProcessedElement == null ? queue.take() : lastSuccessfullyProcessedElement; // blocking

        boolean successful = process(obj);

        if(!successful) {
            lastSuccessfullyProcessedElement = obj;
        } else {
            lastSuccessfullyProcessedElement = null;
        }
    }
}
  1. Llamando peek() y comprobar si el valor es nulo no es CPU eficiente.

He visto uso de la CPU va a 10% en mi sistema cuando la cola está vacía para el siguiente programa.

while (true) {
   Object o = queue.peek();
   if(o == null) continue;
   // omitted for the sake of brevity
}
  1. Adición sleep() suma lentitud.

  2. Adición de nuevo a la cola mediante putLast se perturbe el orden. Además, es una operación de bloqueo que requiere cerraduras.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top