2011-09-06 9 views
9

Potrzebuję Object, aby być asynchronicznie powiadamiany, gdy niektóre BlockingQueue ma przedmiotu do podania.Będąc asynchronicznie powiadamiane o BlockingQueue posiadające element dostępny

Rozglądałem zarówno Javadoc oraz w internecie na pre-made roztworze, a następnie skończyło się z (być może naiwne) roztworu kopalni, to jest tutaj:

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

i

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) { 
      } 
     } 
    } 
} 

Zasadniczo, jest to wątek blokowania na take() funkcjonowania kolejki wywołań zwrotnych że obiekt słuchacza każdym razem operacja take() powiedzie, ewentualnie odesłanie specjalną cookie obiekt (zignorować, jeśli chcesz).

Pytanie brzmi: czy istnieje lepszy sposób na zrobienie tego? Czy popełniam niewybaczalny błąd (zarówno pod względem współbieżności/wydajności i/lub czystości kodu)? Z góry dziękuję.

Odpowiedz

10

Może podklasy niektóre BlockingQueue (takich jak ArrayBlockingQueue lub LinkedBlockingQueue czy co tam używasz), dodać wsparcie dla słuchaczy i czy

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

Podoba mi się. Jedynym problemem jest to, jak mogę go podklasować, ponieważ nie lubię ograniczać się do konkretnej implementacji BlockingQueue ... tj. Jeśli mam podklasę LinkedBlockingQueue, to jestem związany z tą implementacją. Czy powinienem zrobić "dekoratora"? – gd1

+4

Tak, dekorator brzmi jak dobry pomysł na ten problem –

0

Wygląda to na dobry standardowy wzorzec blokowania i słuchania kolejki. Dokonujesz dobrego wyboru, tworząc interfejs słuchacza. Jeśli nie korzystasz z klasy BlockingQueue (której nie znam), jedyną rzeczą, którą masz do zarządzania, jest poprawne wait() i notify() zarządzanie połączeniem blokującym.

Ten szczególny SO Pytanie "A simple scenario using wait() and notify() in java" zapewnia dobry przegląd na oczekiwania i powiadomić i korzystanie związane BlockingQueue

+0

Czy możesz mi powiedzieć więcej na temat użycia wait() i notify() w tym przypadku? – gd1

+0

Oczekiwanie i powiadomienie to metoda radzenia sobie z problemem konsumenta producenta (na przykład kolejka blokująca) przed wprowadzeniem klasy BlockingQueue, na którą odpowiedziała usługa aiobee. Zobacz to pytanie ogólne http://stackoverflow.com/questions/2536692/a-simple-scenario-using-wait-and-notify-in-java w celu uzyskania dokładnej ilustracji. Jeśli google "czekaj i powiadamiaj kolejkę Java", znajdziesz wiele podobnych odniesień, takich jak http://download.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html lub http: //www.javamex. com/tutorials/synchronization_producer_consumer.shtml – momo

+0

Wiedziałem o wait() i notify(), ale pomyślałem, że użycie BlockingQueue poradziłoby sobie z tym po instalacji (w rzeczywistości, w podanym przykładzie, istnieje implementacja BlockingQueue jako wait()/notify() scenariusz użycia) :) – gd1