2012-03-06 20 views
12

Tengo múltiples BlockingQueues que contienen mensajes para enviar. ¿Es posible tener menos consumidores que colas? No quiero repetir las colas y seguir sondeándolas (ocupado esperando) y no quiero un hilo para cada cola. En cambio, me gustaría tener un hilo que se despierte cuando un mensaje esté disponible en cualquiera de las colas.Colas de bloqueo múltiples, consumidor único

+5

¿Cuál es la diferencia entre esto y una única cola de bloqueo que se otorga a múltiples productores? –

+0

Creo que lo que Alex quiere lograr es crear una cola de bloqueo (wrapper) sobre múltiples colas de bloqueo para que el consumidor simplemente espere en una sola cola de bloqueo. Tal vez la situación impide que Alex exija a los productores que utilicen la misma instancia de cola de bloqueo. – sjlee

+1

El problema es que no quiero consumidores múltiples por cola. Si lo volcara todo en una fila, los consumidores podrían comer de la misma fila. Así que si tengo una cola con A y una cola con B's. No se puede tomar B mientras se siga tomando otra B. – Alex

Respuesta

6

Un truco que podría hacer es tener una cola de colas. Entonces, lo que harías es tener una sola cola de bloqueo a la que se suscriben todos los hilos. Luego, cuando encola algo en una de sus BlockingQueues, también pone en cola su cola de bloqueo en esta única cola. Por lo que tendría algo como:

BlockingQueue<WorkItem> producers[] = new BlockingQueue<WorkItem>[NUM_PRODUCERS]; 
BlockingQueue<BlockingQueue<WorkItem>> producerProducer = new BlockingQueue<BlockingQueue<WorkItem>>(); 

Entonces, cuando llegue un nuevo elemento de trabajo:

void addWorkItem(int queueIndex, WorkItem workItem) { 
    assert queueIndex >= 0 && queueIndex < NUM_PRODUCERS : "Pick a valid number"; 
    //Note: You may want to make the two operations a single atomic operation 
    producers[queueIndex].add(workItem); 
    producerProducer.add(producers[queueIndex]); 
} 

Ahora sus consumidores pueden todos bloque en el producerProducer. No estoy seguro de cuán valiosa sería esta estrategia, pero sí logra lo que desea.

+0

¡Simple y efectivo! ¡Gracias! – Alex

+0

@Alex: No hay problema - Tengo mucha curiosidad por cómo funciona. – mindvirus

4

El LinkedBlockingMultiQueue hace lo que está pidiendo. No permite al consumidor bloquear en BlockingQueues arbitrarias, pero es posible crear "sub colas" desde una única "multi queue" y lograr el mismo efecto. Los productores ofrecen en las sub colas, y los consumidores pueden bloquearse a sí mismos sondeando la única cola múltiple, esperando cualquier elemento.

También admite prioridades, es decir, toma elementos de algunas colas antes de considerar otras.

Ejemplo:

LinkedBlockingMultiQueue<Int, String> q = new LinkedBlockingMultiQueue<>(); 
q.addSubQueue(1 /* key */, 10 /* priority */); 
q.addSubQueue(2 /* key */, 10 /* priority */); 
LinkedBlockingMultiQueue<Int, String>.SubQueue sq1 = q.getSubQueue(1); 
LinkedBlockingMultiQueue<Int, String>.SubQueue sq2 = q.getSubQueue(2); 

A continuación, puede ofrecer y sondeo:

sq1.offer("x1"); 
q.poll(); // "x1" 
sq2.offer("x2"); 
q.poll(); // "x2" 

responsabilidad: yo soy el autor de la biblioteca.

Cuestiones relacionadas