Stany wątków są częstym pytaniem na rozmowie kwalifikacyjnej z działu wielowątkowości. W Javie wątki mogą znajdować się w sześciu stanach. Każda zmiana stanu poprzedzona jest jakimś zdarzeniem. Co to za zdarzenia? Zapraszam do wpisu, aby się o tym dowiedzieć!
Stan
Aby pobrać stan wątku wykorzystujemy wbudowaną metodę getState(), która znajduje się w klasie Thread:
Jak napisałem we wstępie, wątek może znajdować się w jednym z sześciu stanów:
NEW
Wątek w stanie NEW znajduje się zaraz po utworzeniu. Posiada on ten stan dopóki nie uruchomimy metody start():
1 2 3 4 5 6 7
@Test voidshouldReturnNewState() { // Given finalThreadnewThread=newThread(); // Then assertThat(newThread.getState()).isEqualTo(Thread.State.NEW); }
RUNNABLE
Po wywołaniu metody start() na wątku, zmienia on swój stan z NEW na RUNNABLE:
1 2 3 4 5 6 7 8 9 10
@Test voidshouldReturnRunnableState()throws InterruptedException { // Given finalThreadrunnableThread=newThread(() -> { assertThat(Thread.currentThread().getState()).isEqualTo(Thread.State.RUNNABLE); }); // When runnableThread.start(); runnableThread.join(); }
BLOCKED
Wątek w stanie BLOCKED może znaleźć się wtedy, kiedy dostęp do sekcji krytycznej jest aktualnie zajęty (znajduje się blokada na monitorze). Innymi słowy, kiedy wątek będzie próbował się dostać do synchronizowanej metody, a wewnątrz znajduje się już inny wątek, to stan zmieniany jest na BLOCKED:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
@Test voidshouldReturnBlockedState()throws InterruptedException { // Given finalThreadsynchronizedThread=newThread(this::synchronizedMethod); finalThreadblockedThread=newThread(this::synchronizedMethod);
// When synchronizedThread.start(); blockedThread.start();
// Then Thread.sleep(10); assertThat(blockedThread.getState()).isEqualTo(Thread.State.BLOCKED); }
WAITING
Zmiana wątku na stan WAITING odbywa się wtedy, gdy wątek czeka na inne wątki. Nie jest to czekanie jak w sekcji krytycznej, tylko czekanie wywołane przykładowo metodą wait() czy join():
// Then Thread.sleep(10); assertThat(wrapperThread.getState()).isEqualTo(Thread.State.WAITING); }
TIMED_WAITING
Każdemu z nas przydarzyło się przenieść wątek w stan uśpienia. Posiada on wtedy stan TIMED_WAITING. Ten stan pojawia się również, gdy używamy metod do czekania na inne wątki (jak wait() czy join()), które w parametrach przyjmują wartości czasowe: