Wprowadzenie do stanu wątku Java z przykładem — cykl życia wątku
Opublikowany: 2019-01-11
Stany wątków
Poniższy diagram ilustruje różne stany, w jakich może znajdować się wątek Javy w dowolnym momencie swojego życia oraz które wywołania metod powodują przejście do innego stanu. Ten diagram nie jest kompletnym diagramem stanów skończonych, ale raczej przeglądem bardziej interesujących i powszechnych aspektów życia wątku.
Jesteś we właściwym miejscu, jeśli masz którekolwiek z poniższych pytań:
- Cykl życia wątku w Javie
- Cykl życia i stany wątku w Javie
- Zrozumienie stanów wątków Java
Pozostała część tej strony omawia Thread's life cycle
pod względem jego stanu.

Nowy wątek
Poniższa instrukcja tworzy nowy wątek, ale go nie uruchamia, pozostawiając wątek w stanie oznaczonym na diagramie jako Nowy wątek.
1 |
Thread myThread = new MyThreadClass ( ) ; |
Gdy wątek jest w stanie New Thread
, jest to po prostu pusty obiekt Thread. Nie przydzielono jeszcze żadnych zasobów systemowych. Tak więc, gdy wątek jest w tym stanie, możesz tylko uruchomić wątek lub go zatrzymać; wywołanie jakiejkolwiek innej metody poza start()
lub stop()
, gdy wątek jest w tym stanie, nie ma sensu i powoduje wyjątek IllegalThreadStateException.
Możliwość uruchomienia
Rozważmy teraz te dwa wiersze kodu:
1 2 |
Thread myThread = new MyThreadClass ( ) ; myThread . start ( ) ; |
Metoda start()
tworzy zasoby systemowe niezbędne do uruchomienia wątku, planuje uruchomienie wątku i wywołuje metodę run()
wątku. W tym momencie wątek jest w stanie „Runnable”. Ten stan nazywa się „Uruchomiony”, a nie „Uruchomiony”, ponieważ wątek może w rzeczywistości nie działać, gdy jest w tym stanie. Wiele komputerów ma jeden procesor, co uniemożliwia jednoczesne uruchamianie wszystkich wątków „Runnable”.
Tak więc system Java Runtime musi zaimplementować schemat planowania, który współdzieli procesor między wszystkimi „Runnable” wątkami. Jednak w większości przypadków stan „Uruchamialny” można traktować jako po prostu „Uruchomiony”. Kiedy wątek jest uruchomiony – jest „Runnable” i jest bieżącym wątkiem – instrukcje w jego run()
są wykonywane sekwencyjnie.
Nie można uruchomić
Wątek przechodzi w stan Not Runnable
można uruchomić, gdy wystąpi jedno z tych czterech zdarzeń:
- ktoś wywołuje jego metodę
suspend()
- ktoś wywołuje jego metodę
sleep()
- wątek używa swojej metody
wait()
do oczekiwania na zmienną warunku - wątek blokuje się na we/wy.
Na przykład pogrubiona linia w tym fragmencie kodu
1 2 3 4 5 6 |
Thread myThread = new MyThreadClass ( ) ; myThread . start ( ) ; try { myThread . sleep ( 10000 ) ; } catch ( InterruptedException e ) { } |
myThread
na 10 sekund (10 000 milisekund). W ciągu tych 10 sekund, nawet gdyby procesor stał się dostępny, myThread
nie działałby. Po upływie 10 sekund myThread
staje się „Runnable” i teraz, jeśli procesor będzie dostępny, myThread
będzie działać.
Dla każdego z „wejść” do stanu „Nie można uruchomić” wymienionego powyżej, istnieje określona i odrębna droga ucieczki, która przywraca wątek do stanu „Uruchamialny”. Droga ewakuacyjna działa tylko dla odpowiadającego jej „wejścia”. Na przykład, jeśli wątek został uśpiony, musi upłynąć określona liczba milisekund, zanim wątek ponownie stanie się uruchamialny. Wywołanie resume()
w uśpionym wątku nie ma żadnego efektu.
Poniżej wskazano drogę ucieczki dla każdego wejścia w stan „Nie da się uruchomić”.
- Jeśli wątek został uśpiony, musi upłynąć określona liczba milisekund.
- Jeśli wątek został zawieszony, ktoś musi wywołać jego metodę
resume()
. - Jeśli wątek czeka na zmienną warunku, dowolny obiekt, który jest właścicielem zmiennej, musi ją porzucić, wywołując
notify()
lubnotifyAll()
. - Jeśli wątek jest zablokowany na we/wy, określone polecenie we/wy musi zostać zakończone.

Martwy
Nić może umrzeć na dwa sposoby: albo z przyczyn naturalnych, albo przez zabicie (zatrzymanie). Wątek umiera naturalnie, gdy jego metoda run()
kończy się normalnie. Na przykład pętla while
w tej metodzie jest pętlą skończoną — wykona iterację 100 razy, a następnie zakończy działanie.

1 2 3 4 5 6 7 |
public void run ( ) { int i = 0 ; while ( i < 100 ) { i ++ ; System . out . println ( "i = " + i ) ; } } |
Wątek z tą metodą run()
umrze naturalnie po zakończeniu pętli i zakończeniu metody run()
.
Możesz także zabić wątek w dowolnym momencie, wywołując jego metodę stop()
. Ten fragment kodu.
1 2 3 4 5 6 7 |
Thread myThread = new MyThreadClass ( ) ; myThread . start ( ) ; try { Thread . currentThread ( ) . sleep ( 10000 ) ; } catch ( InterruptedException e ) { } myThread . stop ( ) ; |
tworzy i uruchamia myThread
a następnie usypia bieżący wątek na 10 sekund. Gdy bieżący wątek się budzi, pogrubiona linia w segmencie kodu zabija myThread
.
Metoda stop()
rzuca obiekt ThreadDeath w wątku, aby go zabić. Tak więc, gdy wątek zostanie zabity w ten sposób, umiera asynchronicznie. Wątek umrze, gdy faktycznie otrzyma wyjątek ThreadDeath.
Niedozwolony wyjątek stanu wątku
System środowiska wykonawczego zgłasza wyjątek IllegalThreadStateException, gdy wywoływana jest metoda w wątku, a stan tego wątku nie zezwala na wywołanie tej metody. Na przykład, IllegalThreadStateException jest generowany, gdy wywołasz suspend()
w wątku, który nie jest „Runnable”.
Jak pokazano w różnych przykładach wątków do tej pory w tej lekcji, po wywołaniu metody wątku, która może zgłosić wyjątek, należy albo przechwycić i obsłużyć wyjątek, albo zadeklarować, że metoda wywołująca zgłasza nieprzechwycony wyjątek.
Metoda isAlive()
I ostatnie słowo o stanie wątku: interfejs programistyczny dla klasy Thread zawiera metodę o nazwie isAlive()
. Funkcja isAlive()
zwraca wartość true, jeśli wątek został uruchomiony, a nie zatrzymany. Tak więc, jeśli metoda isAlive()
zwróci wartość false , wiesz, że wątek jest „Nowym Wątkiem” lub „Martwym”.
Jeśli metoda isAlive()
zwróci true , wiesz, że wątek jest albo „Możliwy do uruchomienia” lub „Nie można go uruchomić”. Nie można odróżnić wątku „Nowego” od „Martwego”; nie można też odróżnić wątku „Runnable” od wątku „Not Runnable”.
Patrząc na złożone przykłady wątków, znalazłem ten naprawdę świetny samouczek w sieci. Każdy powinien to uważnie przeczytać.