Состояние потоков – распространенный вопрос на собеседовании при приеме на работу, связанную с многопоточностью.
В Java потоки могут находиться в шести состояниях.
Каждому изменению состояния предшествует какое-то событие.
Что это за события? Приглашаю вас в пост, чтобы узнать!
Состояние
Для получения состояния потока мы используем встроенный метод getState(), находящийся в классе Thread:
final Thread newThread = new Thread();
newThread.getState();
Code language: PHP (php)
Как я уже писал во введении, поток может находиться в одном из шести состояний:
NEW
Поток находится в состоянии NEW сразу после его создания. Он сохраняет это состояние до тех пор, пока мы не выполним метод start():
@Test
void shouldReturnNewState() {
// Given
final Thread newThread = new Thread();
// Then
assertThat(newThread.getState()).isEqualTo(Thread.State.NEW);
}
Code language: PHP (php)
RUNNABLE
Когда метод start() вызывается для потока, он изменяет свое состояние с NEW на RUNNABLE:
@Test
void shouldReturnRunnableState() throws InterruptedException {
// Given
final Thread runnableThread = new Thread(() -> {
assertThat(Thread.currentThread().getState()).isEqualTo(Thread.State.RUNNABLE);
});
// When
runnableThread.start();
runnableThread.join();
}
Code language: JavaScript (javascript)
BLOCKED
Поток в состоянии BLOCKED можно найти, если доступ к критической секции в данный момент занят (есть блокировка на мониторе).
Другими словами, когда поток пытается получить доступ к синхронизированному методу, а другой поток уже находится внутри, состояние изменяется на BLOCKED:
@Test
void shouldReturnBlockedState() throws InterruptedException {
// Given
final Thread synchronizedThread = new Thread(this::synchronizedMethod);
final Thread blockedThread = new Thread(this::synchronizedMethod);
// When
synchronizedThread.start();
blockedThread.start();
// Then
Thread.sleep(10);
assertThat(blockedThread.getState()).isEqualTo(Thread.State.BLOCKED);
}
Code language: PHP (php)
WAITING
Переход потока в состояние WAITING происходит, когда поток ожидает другие потоки.
Это не ожидание, как в критической секции, а ожидание, вызываемое, например, методом wait() или join():
@Test
void shouldReturnWaitingState() throws InterruptedException {
// Given
final Thread waitingThread = new Thread(this::synchronizedMethod);
final Thread wrapperThread = new Thread(() -> {
waitingThread.start();
try {
Thread.currentThread().join();
} catch(InterruptedException e) {
e.printStackTrace();
}
});
// When
wrapperThread.start();
// Then
Thread.sleep(10);
assertThat(wrapperThread.getState()).isEqualTo(Thread.State.WAITING);
}
Code language: PHP (php)
TIMED_WAITING
С каждым из нас случалось усыпить поток. Затем он переходит в состояние TIMED_WAITING.
Это состояние также появляется, когда мы используем методы для ожидания других потоков (например, wait() или join()), которые принимают значения времени в качестве параметров:
@Test
void shouldReturnTimedWaitingState() throws InterruptedException {
// Given
final Thread timedWaitingThread = new Thread(() -> {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// When
timedWaitingThread.start();
// Then
Thread.sleep(10);
assertThat(timedWaitingThread.getState()).isEqualTo(Thread.State.TIMED_WAITING);
}
Code language: JavaScript (javascript)
TERMINATED
Когда поток завершает свою работу (то есть, когда завершается метод run()), он переходит в состояние TERMINATED:
@Test
void shouldReturnTerminatedState() throws InterruptedException {
// Given
final Thread terminatedThread = new Thread(()->{});
// When
terminatedThread.start();
terminatedThread.join();
// Then
assertThat(terminatedThread.getState()).isEqualTo(Thread.State.TERMINATED);
}
Code language: JavaScript (javascript)