2012-09-20 15 views
8

Powiel możliwe:
Java Executors: how can I set task priority?Reorder kolejka w ThreadPoolExecutor Java

mam ThreadPoolExecutor zbudowany przy użyciu LinkedBlockingDequeue i chcę manipulować kolejkę podstawowej, jednak czytając to w dokumentacji sprawia, bardzo się denerwuję.

utrzymanie kolejki

Metoda getQueue() pozwala na dostęp do kolejki pracować dla celów monitorowania i debugowania. Używanie tej metody do jakichkolwiek innych celów jest zdecydowanie odradzane. Dwie dostarczone metody, remove (java.lang.Runnable) i purge() są dostępne, aby pomóc w odzyskiwaniu pamięci, gdy duża liczba oczekujących zadań zostanie anulowana.

szczególności chcę móc

  1. Sprawdź kolejkę, aby zobaczyć, czy element istnieje. Zakładam, że to jest w porządku, ponieważ żadne zablokowanie nie powinno być konieczne, aby po prostu wyświetlić elementy w kolejce.
  2. Chcę zmienić kolejność kolejki na podstawie jakiegoś sygnału. To oczywiście może być kłopotliwe. Zastanawiam się, czy istnieje preferowany sposób, aby to zrobić, aby nie zepsuć kolejki do innych zastosowań.

Dzięki

+0

Jak wynika z dokumentacji, nie należy kontrolować kolejki w tej metodzie. Powinieneś kontrolować go z kolejki, którą przekazałeś do swojego "ThreadPoolExecutor". – pickypg

+0

Ale czy to nadal nie wiąże się z ryzykiem problemów z gwintowaniem? Pomyślałem, że jeśli wywołasz metodę getQueue(), to jest to samo, co modyfikowanie faktycznego obiektu kolejki, który przekazuję. – Jon

+2

Nie sądzę, mogę użyć PriorityComparator zgodnie z sugestią w drugim pytaniu, ponieważ PriorityComparator nie zapewnia sposób porządkowania elementów, gdy są one w kolejce. – Jon

Odpowiedz

4

getQueue() zawsze zwraca dokładną BlockingQueue<Runnable> które przechodzą do ThreadPoolExecutor.

Niepokojące z dokumentacją jest to, że można łatwo napotkać problemy z podwójnym uruchomieniem, jeśli nie można zagwarantować bezpieczeństwa wątku BlockingQueue. Jeśli używasz PriorityBlockingQueue i używasz tylko remove i add (lub, bardziej bezpośrednio, offer), będziesz bezpieczny, możesz nawet zrobić to bezpośrednio z poziomu getQueue().

Innymi słowy, gdy sygnał informuje, że priorytetem niektóre Runnable „s uległa zmianie, to należy go remove i sprawdzić wynik remove (true jeśli usunięty), i tylko wtedy, gdy został rzeczywiście usunięty, a następnie powinien ponownie dodać. Nie można zagwarantować, że coś nie zostanie przechwycone pomiędzy tymi operacjami, ale masz przynajmniej gwarancję, że nie uruchomisz podwójnie Runnable, co może się łatwo zdarzyć, jeśli zrobisz to z contains ->remove ->add.

Albo, albo możesz napisać własną implementację BlockingQueue, która używa Comparator (jak PriorityBlockingQueue), która znajduje najwyższy priorytet za każdym razem, gdy poprosi o nowe dane. To brzmi jak dużo więcej pracy, biorąc pod uwagę różne interfejsy.