Pregunta

Me gustaría tener un SynchronousQueue donde inserto elementos de un hilo con put () , por lo que la entrada se bloquea hasta que el elemento se toma en otro hilo.

En el otro hilo realizo muchos cálculos y de vez en cuando quiero verificar si un elemento ya está disponible y consumirlo. Pero parece que isEmpty () siempre devuelve verdadero, incluso si otro hilo está esperando en la llamada put () .

¿Cómo es esto posible? Aquí está el código de muestra:

@Test
public void testQueue() throws InterruptedException {
    final BlockingQueue<Integer> queue = new SynchronousQueue<Integer>();

    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                if (!queue.isEmpty()) {
                    try {
                        queue.take();
                        System.out.println("taken!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // do useful computations here (busy wait)
            }
        }
    });
    t.start();

    queue.put(1234);
    // this point is never reached!
    System.out.println("hello");
}

EDITAR: Ni isEmpty () ni peek () funcionan, uno tiene que usar poll (). Gracias!

¿Fue útil?

Solución

De http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/SynchronousQueue.html#put(E) :

isEmpty
public boolean isEmpty ()
Siempre vuelve verdadero. Un SynchronousQueue no tiene capacidad interna.

(no he analizado esto con gran detalle, pero es posible que desee echar un vistazo a encuesta o tomar en su lugar)

Otros consejos

Además de la respuesta de Tim: no está haciendo nada en el hilo del consumidor, sino que llama continuamente a isEmpty () en un ciclo cerrado. En lugar de pedirle al sistema operativo que no lo ejecute hasta que haya algo útil para hacer, el hilo del consumidor está continuamente ocupado. Incluso si isEmpty funcionó correctamente, el hilo productor rara vez tendría la oportunidad de ejecutarse.

Podría (si isEmpty () funcionó, o cambió a usar poll ()) hacer que el consumidor duerma un poco entre pruebas cuando la cola está vacía para darle al productor la oportunidad de correr, o (preferiblemente) solo saque la prueba isEmpty () y deje que el hilo se bloquee en el mutex dentro de take () de manera sensata en lugar de sondear.

parece que su código está intentando hacer una encuesta. ¿Por qué no simplemente llamar al método poll ()?

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