Programming/JAVA

JAVA에서의 스레드의 상태

khj1999 2024. 10. 22. 19:30

자바 스레드는 여러 상태(state)를 가지며, 각 상태는 스레드가 실행 중이거나 실행을 기다리는
다양한 단계를 나타낸다.
자바 스레드의 상태는 Thread.State 열거형(Enum)으로 정의되어 있으며
총 6가지 주요 상태가 있다:NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.
아래는 각 상태에 대한 설명이다.

1. NEW (새로운 상태)

  • 설명: 스레드 객체가 생성되었지만 아직 start() 메서드가 호출되지 않은 상태.
    이때는 스레드가 시작되지 않았으며, 작업을 수행하지 않고 있음

  • 상태 진입 시점: 스레드가 처음 생성되었을 때.

      Thread t = new Thread();  // 상태: NEW

2. RUNNABLE (실행 가능한 상태)

  • 설명: 스레드가 실행 준비가 되어 CPU에서 실행될 수 있는 상태.
    스레드는 실행 대기열에 올라가며, 운영체제가 스케줄링에 따라 스레드가 실제로 실행될 기회를 얻는다.
    자바에서는 RUNNINGRUNNABLE 상태를 구분하지 않고 모두 RUNNABLE로 간주합다.
    따라서 실제로 실행 중이거나 CPU 할당을 기다리는 상태 모두가 RUNNABLE 이다.

  • 상태 진입 시점: start() 메서드를 호출한 후.

      t.start();  // 상태: RUNNABLE (실행 대기 중)

3. BLOCKED (차단 상태)

  • 설명: 스레드가 락(lock)을 얻지 못해 실행을 일시적으로 중단한 상태.
    이 상태는 스레드가 synchronized 블록 또는 메서드에서 사용 중인 자원(예: 모니터 락)에 접근하려고
    하지만, 다른 스레드가 그 자원을 소유하고 있을 때 발생. 스레드는 락이 해제될 때까지 차단된다.

  • 상태 진입 시점: 스레드가 락을 기다리는 동안.

      synchronized (lock) {
          // lock을 얻을 때까지 BLOCKED 상태
      }

4. WAITING (대기 상태)

  • 설명: 스레드가 특정 조건이 충족될 때까지 기다리는 상태.
    이 상태에서 스레드는 스케줄링에 의해 다시 실행되지 않으며,
    다른 스레드가 해당 스레드를 깨워주기 전까지(예: notify() 또는 notifyAll() 호출) 대기. Object.wait(), Thread.join() 또는 LockSupport.park() 메서드를 호출했을 때 스레드는 WAITING 상태로 진입한다.

  • 상태 진입 시점: 스레드가 wait(), join() 등에 의해 대기할 때.

      synchronized (lock) {
          lock.wait();  // 상태: WAITING
      }

5. TIMED_WAITING (시간 제한 대기 상태)

  • 설명: WAITING 상태와 유사하지만, 특정 시간 동안만 대기하는 상태.
    주어진 시간만큼 기다린 후에도 조건이 충족되지 않으면 스레드는 자동으로 RUNNABLE 상태로 돌아간다. sleep(), wait(long timeout), join(long timeout), LockSupport.parkNanos()와 같은
    메서드를 호출했을 때 이 상태로 진입한다.

  • 상태 진입 시점: 스레드가 시간 제한이 있는 대기를 시작할 때.

      Thread.sleep(1000);  // 상태: TIMED_WAITING (1초 동안 대기)

6. TERMINATED (종료 상태)

  • 설명: 스레드의 작업이 모두 완료되어 더 이상 실행되지 않는 상태.
    스레드가 정상적으로 종료되었거나 예외가 발생하여 종료된 경우 모두 TERMINATED 상태가 된다.
    이 상태에서는 스레드가 다시 실행될 수 없다.

  • 상태 진입 시점: run() 메서드가 정상적으로 종료되거나 예외로 인해 종료될 때.

      // run() 메서드가 끝나면
      // 상태: TERMINATED

스레드 상태 간의 전이(Transition)

스레드는 위의 상태들 사이에서 다음과 같이 전이된다:

  • NEW → RUNNABLE: start() 호출.
  • RUNNABLE → BLOCKED: 락이 필요할 때.
  • RUNNABLE → WAITING: wait(), join() 등이 호출될 때.
  • RUNNABLE → TIMED_WAITING: sleep(), wait(long), join(long) 등이 호출될 때.
  • RUNNABLE → TERMINATED: run() 메서드가 종료되면.
  • BLOCKED → RUNNABLE: 락이 해제되면.
  • WAITING → RUNNABLE: notify(), notifyAll() 등이 호출되면.
  • TIMED_WAITING → RUNNABLE: 지정된 시간이 지나면.

스레드 상태 다이어그램

  +------------------------------------+
  |            NEW                     |
  +------------------------------------+
                 |
                 v
  +------------------------------------+
  |           RUNNABLE(RUNNING)        |
  +------------------------------------+
     |                |                |
     v                v                v
+--------+       +-----------+      +-----------+
| BLOCKED|       | WAITING   |      |TIMED_WAITING|
+--------+       +-----------+      +-----------+
                               |
                               v
                          +----------+
                          |TERMINATED|
                          +----------+

결론

  • NEW: 스레드가 생성되었지만 아직 시작되지 않은 상태.
  • RUNNABLE: 스레드가 실행 중이거나 실행될 준비가 된 상태.
  • BLOCKED: 스레드가 자원을 얻기 위해 기다리는 상태.
  • WAITING: 스레드가 다른 스레드의 신호를 기다리는 상태.
  • TIMED_WAITING: 스레드가 주어진 시간 동안 대기하는 상태.
  • TERMINATED: 스레드가 작업을 완료하고 종료된 상태.