Zakańczanie/wstrzymywanie pracy serwera wielowątkowego

0

Mam pytanie na które nie mogę znaleźć odpowiedzi.
Mam Selector który działa sobie w pętli while (true) na osobnym wątku (klasa implementuje Runnable). Uruchamiam wątek za pomocą ExecutorService. Chciałbym wstrzymać jego pracę/zabić instancję. Jak to zrobić?
Czy powinienem:

  • rzucić jakiś wyjątek, aby wywołać przerwanie (wydaje mi się to okropnym pomysłem)
  • korzystać z Observable
  • trzymać obiekt Future i na nim operować?

Każda pomoc i dyskusja mile widziane.

1

Nie da się w Javie zatrzymać wątku. Możesz jedynie w tym Runnable zawołać Thread::interrupt czym zasugerujesz executor service, aby zatrzymał wątek, ale kiedy to nastąpi ciężko powiedzieć. Jeżeli aktualnie nie jesteś na jakiejś blokującej metodzie to powinno to stać się szybko. Jeżeli metoda blokująca jest dobrze napisana to rzuci InterruptedException i też skończy się w miarę szybko.

To jak responsywny w zamykaniu będzie Twój wątek zależy również od tego jakie metody tego Selectora używasz, select z timeoutem może Ci pomóć zwiększyć responsywność na sygnał zakończenia, ale kosztem CPU.

0

@nie100sowny: Czy w takim razie jest jakaś możliwość edytowania warunku pętli?
Nie mogę zatrzymać wątku, ale mogę zatrzymać pętlę - tylko pytanie teraz brzmi jak inteligentnie poinformować drugi wątek (czytaj wymienić informację między dwoma wątkami: sterującym i wykonawczym) tak, aby niepotrzebnie nie obciążać mojego wątku wykonawczego jakimś skomplikowanym sprawdzaniem, ale tak, żeby zauważył zmianę?
Jakieś teorie?

3

Warunek nie wiele pomoże. Po pierwsze musi to być zmienna volataile, aby mieć gwarancję odczytu, ale wciąż problem pozostaje ten sam:

  1. Warunek końca == true.
  2. Wołamy Selector::select i wątek się blokuje
  3. Ktoś ustawia warunek końca == false, ale nasz wątek wciąż jest zablokowany na select i tego nie widzi.

Ogólnie z tego co pamiętam dodanie Thread::isInterrupted do warunku while() to dobra praktyka.

Rozwiązania:

  1. Używać Selector::select z timeout np. 20 ms.
  2. Gdy chcesz zakończyć zawołać ExecutorService::shutdown / ExecutorService::awaitTermination musisz poczytać, bo concurrency to trudny temat, a ja ostatni raz w tym siedziałem z 2 lata temu :)
  3. Możesz też zamiast ExecutorService stworzyć wątek, wówczas z zewnątrz wołasz Thread::interrupt i Thread::join i wówczas możesz zaczekać na zakończenie wątku. Powinno działać o ile Runnable będzie respektował przerwania.

Porada:
Zajrzyj sobie do "Java Concurrency in Practice" Chapter 7: Cancellation and Shutdown

0

@nie100sowny: oczywiscie ze sie da zatrzymac. Ale sposob w jaki to mozna zrobic definitywnie nie nadaje sie na produkcje :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1