본문 바로가기
Java

자바 스레드 (3) - 스레드 생명주기와 상태

by gentle-tiger 2025. 6. 10.
프로젝트 중 느낀 자바 기초의 부족함을 보완하고자 핵심 주제를 순차적으로 복습할 예정입니다.
자바 코어 → 자바 스레드 → 자바 OOP → 자바의 예외 → 자바의 컬렉션 → 최대 절전 모드 순으로 정리할 예정입니다. 

 

스레드 생명주기와 상태

  1. 스레드의 생명주기에 대해 설명하시오.
  2. Java에서 죽은 스레드를 다시 시작할 수 있습니까?
  3. Java에서 이미 시작된 스레드를 다시 시작할 수 있습니까?
  4. 한 스레드가 다른 스레드를 차단할 수 있습니까?

 

 

스레드의 생명주기에 대해 설명하시오.

자바에서 스레드의 생명주기(Thread Life Cycle) 는 크게 NEW → RUNNABLE → RUNNING → BLOCKED/WAITING/TIMED_WAITING → TERMINATED 단계로 나뉩니다. 스레드는 생성 후 start() 호출 전까지는 NEW 상태이며, start()가 호출되면 JVM의 스레드 스케줄러에 의해 RUNNABLE 상태로 진입합니다. 이후 CPU가 할당되면 실행 상태(RUNNING)가 되고, 동기화 자원 획득 대기나 sleep(), wait() 호출 등으로 인해 BLOCKED, WAITING, TIMED_WAITING 상태로 전이될 수 있습니다.

작업이 종료되거나 예외가 발생하면 스레드는 TERMINATED (또는 DEAD) 상태로 이동하게 되며, 이 상태에서는 더 이상 재실행이 불가능합니다. 스레드 상태는 Thread.getState() 메서드를 통해 확인할 수 있으며, 상태 전이는 명시적 또는 JVM/OS 스케줄링에 의해 결정됩니다. 멀티스레드 설계 시 스레드 상태 전이 시점에 따른 자원 접근, 동기화 순서, 예외 처리 로직 등을 명확히 고려해야 합니다.

 

 

Java에서 죽은 스레드를 다시 시작할 수 있습니까?

자바에서 한 번 실행이 완료되어 TERMINATED 상태(일명 "죽은 스레드")가 된 스레드는 다시 시작할 수 없습니다. 즉, Thread 객체는 한 번만 실행이 가능하며, 종료된 스레드에 대해 start() 메서드를 호출하면 IllegalThreadStateException 이 발생합니다. 이 동작은 JVM 내부적으로 Thread 객체의 상태 필드로 관리되며, 스레드 상태가 TERMINATED인 경우에는 start() 호출이 무효화됩니다.

따라서 동일한 로직을 다시 실행하려면 새로운 Thread 인스턴스를 생성해야 합니다. 스레드 재사용이 필요한 상황에서는 직접 스레드를 생성하는 대신, ExecutorService나 ThreadPoolExecutor 등의 스레드 풀을 활용하여 작업을 큐에 제출하는 방식이 권장됩니다. 이렇게 하면 스레드의 재사용은 내부적으로 관리되고, 개발자는 스레드의 상태를 직접 제어할 필요 없이 안정적으로 반복 실행을 구현할 수 있습니다.

 

 

Java에서 이미 시작된 스레드를 다시 시작할 수 있습니까?

Thread 객체는 한 번만 실행 가능하며, start()는 단 한 번만 호출할 수 있습니다. 이미 start()가 호출된 스레드는 RUNNABLE 상태이거나 이미 종료되었을 가능성이 있으며, 이러한 상태에서 다시 start()를 호출하면 IllegalThreadStateException 이 발생합니다. 이 제약은 Thread 객체가 OS의 네이티브 스레드와 매핑되는 구조로 설계되어 있기 때문에 존재합니다.

만약 동일한 작업을 여러 번 반복 실행하고자 한다면, Runnable 구현체를 재사용하거나 새로운 Thread 객체를 생성해야 하며, 실무에서는 일반적으로 ExecutorService.submit(Runnable) 혹은 CompletableFuture.runAsync() 등의 방식으로 작업을 큐에 제출하는 패턴을 사용합니다. 이러한 방식은 스레드 재사용 및 작업 관리가 분리되어 구조가 더 안정적이고 유지보수가 용이합니다.

 

 

한 스레드가 다른 스레드를 차단할 수 있습니까?

한 스레드가 직접적으로 다른 스레드의 실행을 차단(Block)할 수는 없습니다. 다만 공유 자원에 대한 경쟁 상황이나 동기화된 블록 또는 메서드를 통한 락(lock) 획득에서 다른 스레드가 락을 보유한 경우, 해당 락을 기다리는 스레드는 BLOCKED 상태로 전이됩니다. 즉, 자바의 스레드 차단은 자원 접근 제어(예: synchronized)에 의해 간접적으로 발생합니다.

예를 들어, 한 스레드가 객체의 모니터 락을 획득한 상태에서 해당 객체의 synchronized 메서드나 블록에 다른 스레드가 진입하려 할 경우, 후속 스레드는 락이 해제될 때까지 BLOCKED 상태로 대기합니다. 이러한 구조는 교착 상태(Deadlock), 기아 상태(Starvation)와 같은 병행성 문제의 원인이 될 수 있으며, 스레드 간 협업 설계 시에는 락 획득 순서, 타임아웃 설정, 재진입 가능 여부 등을 신중히 고려해야 합니다.