Domanda

Vorrei avere un SynchronousQueue dove inserisco elementi da un thread con put () , quindi l'input viene bloccato fino a quando l'elemento viene preso in un altro thread.

Nell'altro thread eseguo molti calcoli e di tanto in tanto voglio verificare se un elemento è già disponibile e consumarlo. Ma sembra che isEmpty () ritorni sempre vero, anche se un altro thread è in attesa alla chiamata put () .

Come diavolo è possibile? Ecco il codice di esempio:

@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");
}

EDIT: Né isEmpty () né peek () funzionano, si deve usare poll (). Grazie!

È stato utile?

Soluzione

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

isEmpty
pubblico booleano isEmpty ()
Restituisce sempre vero. Un SynchronousQueue non ha capacità interna.

(non l'ho esaminato in dettaglio, ma potresti dare un'occhiata a sondaggio o prendi invece)

Altri suggerimenti

Oltre alla risposta di Tim: non stai facendo nulla nel thread consumer ma chiama continuamente isEmpty () in un ciclo stretto. Invece di chiedere al sistema operativo di non eseguirlo fino a quando non c'è qualcosa di utile da fare, il thread del consumatore è costantemente occupato. Anche se isEmpty ha funzionato correttamente, il thread del produttore raramente avrebbe la possibilità di essere eseguito.

Potresti (se isEmpty () ha funzionato, o sei passato all'utilizzo di poll ()) far dormire il consumatore per un po 'tra i test quando la coda è vuota per dare al produttore la possibilità di eseguire, o (preferibilmente) solo elimina il test isEmpty () e lascia che il thread si blocchi sul mutex all'interno di take () in modo sensato anziché effettuare il polling.

sembra che il tuo codice stia provando a fare un sondaggio. perché non chiamare semplicemente il metodo poll ()?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top