Карта / Многопоточность / Состояния потоков

Состояния потоков

Состояния потока — поток проходит через них за свою жизнь:

NEW start() RUNNABLE TERMINATED run() done BLOCKED WAITING TIMED_WAITING ждёт монитор wait()/join() sleep(ms)/wait(ms)
  • NEW — объект Thread создан, но start() не вызван.
  • RUNNABLE — выполняется или ждёт своей очереди у процессора.
  • BLOCKED — ждёт освобождения монитора (synchronized-блока, который занят другим потоком).
  • WAITING — ждёт сигнала бесконечно: wait(), join() без таймаута.
  • TIMED_WAITING — ждёт с таймаутом: sleep(ms), wait(ms), join(ms).
  • TERMINATEDrun() завершился.
Thread t = new Thread(() -> Thread.sleep(1000));
System.out.println(t.getState()); // NEW
t.start();
System.out.println(t.getState()); // RUNNABLE или TIMED_WAITING
Копнуть глубже

BLOCKED vs WAITING — частая путаница. Оба состояния означают «поток не работает», но причина разная:

  • BLOCKED — поток хочет войти в synchronized-блок, но монитор занят. Он ждёт автоматически, без явного вызова.
  • WAITING — поток сам решил подождать вызвав wait() или join(). Нужен явный notify() или завершение другого потока чтобы выйти.

Thread.getState() — получить текущее состояние (полезно при дебаггинге). В продакшне состояния потоков видны в thread dump (jstack PID или через Actuator /actuator/threaddump).

Почему sleep() не освобождает монитор. Thread.sleep() переводит поток в TIMED_WAITING но не отпускает synchronized-монитор если поток его держит — это частая ошибка, которая приводит к deadlock или длинным задержкам:

synchronized (lock) {
    Thread.sleep(1000); // монитор держится всю секунду!
    // другие потоки не могут войти в synchronized(lock)
}
// правильно: если нужно ждать внутри synchronized — используйте lock.wait()
// wait() отпускает монитор на время ожидания
🎤 Закрыл тему, если можешь объяснить:
• все состояния потока и что в каждое переводит;
• разницу BLOCKED и WAITING, и почему sleep() не отпускает монитор (если дошёл до 2-го слоя).