2011-09-06 9 views
9

Ho bisogno di un Object per essere avvisato in modo asincrono quando alcuni BlockingQueue hanno un articolo da fornire.Notifica asincrona di un BlockingQueue con un articolo disponibile

Ho cercato sia Javadoc e il web per una soluzione pre-fatto, quindi ho finito con una soluzione (forse ingenua) di mine, qui è:

interface QueueWaiterListener<T> { 
    public void itemAvailable(T item, Object cookie); 
} 

e

class QueueWaiter<T> extends Thread { 

    protected final BlockingQueue<T> queue; 
    protected final QueueWaiterListener<T> listener; 
    protected final Object cookie; 

    public QueueWaiter(BlockingQueue<T> queue, QueueWaiterListener<T> listener, Object cookie) { 
     this.queue = queue; 
     this.listener = listener; 
     this.cookie = cookie; 
    } 

    public QueueWaiter(BlockingQueue<T> queue, QueueWaiterListener<T> listener) { 
     this.queue = queue; 
     this.listener = listener; 
     this.cookie = null; 
    } 

    @Override 
    public void run() { 
     while (!isInterrupted()) { 
      try { 
       T item = queue.take(); 
       listener.itemAvailable(item, cookie); 
      } catch (InterruptedException e) { 
      } 
     } 
    } 
} 

Fondamentalmente, c'è un blocco di thread su un'operazione take() di una coda che richiama un oggetto listener ogni volta che un'operazione take() riesce, facoltativamente inviando un oggetto speciale cookie (ignorarlo se lo si desidera).

La domanda è: c'è un modo migliore per farlo? Sto facendo un errore imperdonabile (sia in concorrenza/efficienza e/o pulizia del codice)? Grazie in anticipo.

risposta

10

forse si potrebbe creare una sottoclasse qualche BlockingQueue (come ArrayBlockingQueue o LinkedBlockingQueue o che cosa mai si sta utilizzando), aggiungere il supporto per gli ascoltatori e fare

@Override 
public boolean add(E o) { 
    super.add(o); 
    notifyListeners(o); 
} 
+3

Mi piace. L'unico problema è che come posso creare una sottoclasse, perché non mi piace legarmi a un'implementazione specifica di BlockingQueue ... cioè se sottoclassi LinkedBlockingQueue, allora sono legato a questa implementazione. Dovrei fare un "decoratore"? – gd1

+4

Sì, un decoratore sembra una buona idea per questo problema –

0

Questo sembra un buon modello standard per il blocco delle code e gli ascoltatori. Fai una buona scelta di fare l'interfaccia del listener. Se non si utilizza la classe BlockingQueue (di cui non sono a conoscenza), l'unica cosa che si ha è la corretta wait() e notify() per la gestione della chiamata di blocco.

Questo particolare SO Domanda "A simple scenario using wait() and notify() in java" offre una buona panoramica su attesa e notificare e l'uso relative al BlockingQueue

+0

Puoi dirmi di più sull'uso wait() e notify() in questo caso? – gd1

+0

Wait and notify è un metodo per gestire il problema del produttore consumer (come la coda di blocco) prima dell'introduzione della classe BlockingQueue a cui ha risposto aiobee. Vedi questa domanda SO http://stackoverflow.com/questions/2536692/a-simple-scenario-using-wait-and-notify-in-java per l'illustrazione esatta. Se esegui google "Attendi e notifica la coda Java", troverai molti riferimenti simili come http://download.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html o http: //www.javamex. com/tutorial/synchronization_producer_consumer.shtml – momo

+0

Sapevo di wait() e notify() ma pensavo che l'utilizzo di un BlockingQueue lo avrebbe gestito immediatamente (in effetti, in un esempio fornito, esiste un'implementazione di BlockingQueue come wait()/notify() scenario di utilizzo) :) – gd1

Problemi correlati