Prawidłowe zamykanie wątku

0

Jaka jest prawidłowa obsługa zakończenia wątku? Chodzi mi o zatrzymanie z poziomu kodu jak i z poziomu np konsoli naciskając klawisze CTRL+C
Mamy np:
W tym podejściu to wiem że musiałbym jakiegoś shutdownHooka zapiąć aby zamknąć wątki.

public void run() {
      while(isActive) {
              //jakas logika
      }
}

public void stopThread() {
      isActive = false;
}

czy powinniśmy to zrobić tak (czy czasem w tym podejściu nie będziemy narażeni na nieprawidłowe wykonanie iteracji?):

public void run() {
      while(!Thread.interrupted()) {
              //jakas logika
      }
}

public void stopThread() {
      interrupt();
}
2

tutaj mozna rozwazyc obydwie opcje, z tym ze uzywanie flagi wymaga volatile, ale nawet to nie do konca pomaga bo...
w sytuacji jesli watek zostanie zatrzymany na jakiejs blokujacej operacji, np .put() z blocking que w momencie w ktorym kolejka jest pelna, to wtedy gdy wykonasz stopThread() ustawiajac flage na false, watek tego nie przeczyta od razu, tylko dopiero w momencie jak sie odblokuje

1

Programowanie interruptami raczej nie jest dobrą praktyką. Jedynie ma sens jak masz jakąś blokującą operacje typu Sleep.

2

Generalnie najlepiej korzystać z Runnable/Callable + ExecutorService + Future. W przypadku gdy mamy jakiś "serwis" w tle to ja bym obsłużył jakąs flagą ;)

2

Drugi kod z flagą interrupted jest najbardziej sensowny, nie używaj własnej flagi.

Cytat z Java Concurrency in Practice: (polecam cały Rodział 7: Cancellation and Shutdown)

Interruption is usually the most sensible way to implement cancellation.

W skrócie używając interrupted dostajesz bonus w postaci InterruptedException

  1. Flaga nie działa gdy zawołasz w wątku metodę blokującą np. Thread::sleep, lub BlockingQueue::take / BlockingQueue::put
  2. Flaga jest zwykle mniej responsywna gdy zawołasz metodę blokującą z timeoutem np. BlockingQueue::offer / BlockingQueue::poll. Musisz wówczas czekać na zakończenie danego timeoutu. Zwykle InteruptedException będzie wyrzucony wcześniej i twoje zakończenie pracy będzie bardziej responsywne. JDK jednak nie daje tutaj żadnych gwarancji.

Co do pytania o połowiczne wykonanie pętli.

  1. Zwykle nie jest to problemem, ponieważ linijka dokonująca zmian jest na końcu. Jeżeli to twój kod to nie zauważy on interruption, jeżeli jakieś blokujące włożenie do kolejki etc. to należy założyć, że autor klasy rzuca wyjątek w poprawnym momencie zachowując spójność stanu.
  2. Gdy pętla zawiera więcej kodu warto sprawdzić ponownie flagę interrupted gdzieś wewnątrz by wątek był bardziej responsywny na zamykanie.
3

Polecam taką stronkę google.pl. Tam wpisujesz frazę, która Cię interesuje i Google zwraca listę wyników. Zwykle w top3 jest odpowiedź. W tym przypadku https://www.baeldung.com/java-thread-stop. Polecam tę metodę! :)

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