2013-09-05 15 views
5

Pracuję nad aplikacją, która w pewnym momencie uruchamia wątek roboczy. Zachowanie tego wątku będzie się znacznie różnić w zależności od parametrów stosowanych go uruchomić, ale poniższa lista właściwości zastosowania:Jak prawidłowo obsługiwać przerwania wątków

  • Będzie to zrobić drobne operacje We/Wy
  • To będzie wydać niewielką czas w bibliotekach 3rd party
  • może utworzyć kilka wątków roboczych dla pewnej podzadania (nici te nie zostaną ponownie wykorzystane po ich zadaniem jest gotowe)
  • to będzie wydawać najwięcej swoich numerów czasowych chrupanie (Brak blokowanie nazywa obecny)

Z powodu możliwego długiego czasu (od 5 minut do kilku godzin, w zależności od wejścia), chcemy być w stanie przerwać obliczenia. Jeśli zdecydujemy się go przerwać, nie będziemy już dbają o wynik, a wątek marnuje cenne zasoby, o ile cały czas działa. Ponieważ kod jest pod naszą kontrolą, the advised way jest użycie przerwania do wskazania przerwania.

Podczas gdy większość przykładów w Internecie dotyczy wątku roboczego, który przechwytuje niektóre metody, nie dotyczy to mnie (similar question here). W tym wątku roboczym jest również bardzo mało wywołań blokujących, w takim przypadku this article radzi, aby ręcznie sprawdzić flagę przerwania. Moje pytanie brzmi: Jak radzić sobie z tym przerwaniem?

Widzę kilka opcji, ale nie mogę zdecydować, które podejście jest najbardziej "czyste". Pomimo mojego praktycznego przykładu, interesuje mnie przede wszystkim "najlepsza praktyka", jak sobie z tym poradzić.

  1. Rzut jakiś niesprawdzony wyjątek: to zabije wątek w szybki i łatwy sposób, ale to przypomina mi o podejście ThreadDeath używanego przez nieaktualnych Thread#stop() metody, ze wszystkimi jego related problems. Widzę, że to podejście jest akceptowalne w posiadanym kodzie (ze względu na znany przepływ logiczny), ale nie w kodzie biblioteki.
  2. Rzuć jakiś sprawdzony wyjątek: zabiłoby to wątek w szybki i łatwy sposób, a także złagodziło problemy podobne do ThreadDeath, wymuszając na programistach obsługę tego zdarzenia. Nakłada to jednak duże obciążenie na kod, wymagając wszędzie wyjątku. Nie ma powodu, że nie wszystko rzuca InterruptedException.
  3. Zamknij metody, używając "najlepszego dotychczasowego wyniku" lub pustego wyniku. Ze względu na liczbę zaangażowanych zajęć będzie to bardzo trudne zadanie. Jeśli nie zostanie podjęta wystarczająca ostrożność, może powstać NullPointerExceptions z pustych wyników, prowadząc do takich samych problemów jak punkt 1. Znalezienie tych przyczyn byłoby niemożliwe w dużych bazach kodu.
+0

Prawdopodobnie mógłbyś spróbować usprawnić (3) w swojej procedurze obsługi przerwań; nadal może być dobrym pomysłem, biorąc pod uwagę połączenie tego z pewnym rodzajem wyjątku RuntimeException. – blgt

Odpowiedz

1

Proponuję sprawdzić Thread.currentThread(). IsInterrupted() okresowo w punktach, w których można bezpiecznie zatrzymać i zatrzymać, jeśli jest ustawiony.

Można to zrobić w metodzie, która sprawdza tę flagę i generuje niestandardowy niezaznaczony wyjątek lub błąd.

+0

Znacie tylko bezpieczne punkty, jeśli cały uruchomiony kod jest pod Państwa kontrolą. Jak poradziłbyś sobie z tym, jeśli kod jest przeznaczony do biblioteki? (Patrz punkt 1 w moim pytaniu) – DieterDP

0

A co z wykorzystaniem ExecutorService do wykonania Runnable? Sprawdź metody, w których możesz określić limit czasu. Na przykład.

ExecutorService executor = Executors.newSingleThreadExecutor(); 
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes. 
executor.shutdown(); 

Tutaj Zadanie oczywiście implementuje Runnable.

+0

Ta odpowiedź mówi mi, w jaki sposób mogę tworzyć przerwania w moim wątku roboczym, ale nie w jaki sposób powinienem je obsłużyć - co jest moim prawdziwym pytaniem. – DieterDP

Powiązane problemy