본문 바로가기
Java

[Java] 스레드 생명주기와 스케줄링

by 태크민 2025. 1. 28.

스레드 상태

스레드는 JVM에 있어 생명체와 같습니다.

스레드는 태어나고(New), 실행하고(Runnable), 잠자고(Sleep), 대기하고(Wait), 종료(Terminated)하는 등의 생명주기(Life Cycle)을 가집니다.

 

 

NEW

스레드가 생성되었지만 아직 실행할 준비가 되지 않은 상태입니다.

Java에서 new Thread()에 의해 스레드 객체가 생성되면 NEW 상태가 됩니다. 

NEW 상태의 스레드스케줄링 되지 않기 때문에 실행될 수 없는 상태입니다.

스케줄링이 뭔가요?

JVM이 RUNNABLE(준비) 상태인 스레드 중에서 하나를 선택하여 실행시키는 과정입니다.

이렇게 선택된 스레드는 CPU의 자원을 할당받아 실제로 실행됩니다. 

 

원래 자바 스레드는 비선점으로 스케줄링을 합니다.

하지만, Window 또는 안드로이드와 같이 멀티 스레딩을 지원하는 운영체제에서 실행되는 경우 JVM은 운영체제의 스레드를 자바 스레드에 매핑시켜 선점형 스케줄링 방식으로 동작하게 됩니다.

 

  • 선택된 스레드는 일정 시간 동안 CPU를 사용합니다.
  • Time Slice가 끝나면, 스레드는 다시 RUNNABLE 상태로 돌아가고, 스케줄러는 다른 스레드를 실행합니다.

 

RUNNABLE

스레드가 현재 실행되고 있거나, 실행 준비되어 스케줄링을 기다리는 상태입니다.

Thread 클래스의 start() 메소드가 호출되면 RUNNABLE (준비) 상태가 됩니다. 그리고 JVM은 RUNNABLE(준비) 상태에 있는 스레드 중에서 하나를 선택하고 실행되는데, 이 때 처음으로 스케줄링되는 스레드는 run()메소드의 첫라인부터 실행을 하게 됩니다.

JVM은 스케줄링 시 우선순위(priorityh)가 높은 스레드를 우선적으로 선택합니다. 만일 우선순위가 동일한 스레드가 여러개 있으면 라운드 로빈(round robit), 즉 돌아가면서 선택하게 됩니다.

실행중인 스레드를 양보할 수도 있나요?

실행 중인 스레드가 만약 yield()를 호출하면 다른 스레드가 스케줄링될 수 있도록 양보할 수 있습니다.

JVM은 현재 실행 중인 스레드를 즉각 RUNNABLE(준비) 상태로 변경하고 다시 스케줄링을 실시하게 됩니다.

하지만, 만약 다른 높은 순위의 스레드가 없거나 동일한 우선순위의 다른 스레드가 없으면 이 스레드가 다시 스케줄링됩니다.

 

TIMED_WAITING

스레드가 sleep (long n)을 호출하여 n밀리초 동안 잠을 자는 상태입니다.

실행중인 스레드가 sleep(mills)을 호출하면 millis밀리초 동안 잠을 자게 됩니다. 이 때 JVM은 이 스레드를 TIME_WAITING 상태로 변경하고 다른 스레드를 스케줄링하게 됩니다.

 

 

BLOCK

스레드가 I/O 작업을 실행하여 I/O작업의 완료를 기다리면서 멈춘(blocked) 상태입니다.

스레드가 I/O 작업을 실행하면 JVM이 자동으로 현재 스레드를 BLOCK 상태로 만들고 다른 스레드를 스케줄링합니다.

BLOCK 상태의 스레드는 I/O작업이 완료될 때까지 스케줄링 되지 않고 대기합니다. 그리고 I/O작업이 완료되면 스레드는 RUNNABLE(준비) 상태가 됩니다.

화면 출력이나 키보드 입력, 프린터 출력, 파입 입출력, 네트워크 데이터 송수신 등 모든 종류의 I/O작업시 BLOCK 상태가 됩니다.

 

WAITING

실행중인 스레드가 어떤 객체 A의 wait() 메소드를 호출하여 다른 스레드로부터 깨워지기를 기다리는 경우입니다. 이 경우 JVM은 해당 스레드를 WAITING 상태로 변경하고 다른 스레드를 스케줄링합니다.

 

이 때 객체 A를 동기화 객체라고 부릅니다. 모든 객체는 java.lang.Object를 상속 받으며 wait() 메소드는 java.lang.Object 클래스의 멤버이므로 모든 객체가 동기화 객체가 될 수 있습니다. 첫 번째 스레드가 객체 A의 A.wait()을 호출하여 기다리고 있을 때, 다른 스레드가 A.notify나 A.notifyAll() 메소드를 호출하게 되면 첫번째 스레드는 깨어나서 RUNNABLE(준비) 상태로 돌아가게 됩니다.

TERMINATED

스레드가 종료된 상태입니다.

실행 중인 스레드가 종료하면 TERMINATED 상태가 되며, JVM은 다른 스레드를 스케줄링하게 됩니다. 

TERMINATED 상태의 스레드는 더이상 RUNNABLE 상태로 돌아올 수 없기 때문에 다시 실행될 수 없습니다.

 


 

스레드 우선순위와 스케줄링

JVM은 철저히 우선순위(Priority)를 기반으로 스레드를 스케줄링합니다. 가장 높은 우선순위의 스레드를 먼저 실행시키며, 동일한 우선순위인 경우에는 돌아가면서 실행시킵니다.

자바 스레드의 우선순위 체계는 다음과 같습니다.

 

최댓값(MAX_PRIORITY) = 10

최솟값(MIN_PRIORITY) = 1

보통값(NORMAL_PRIORITY) =5

 

자바 응용프로그램이 실행될 때 처음으로 생성되는 main 스레드는 보통 값(5)의 우선순위로 태어나며, 자식 스레드는 생성될 때 부모 스레드의 우선순위 값을 물려받기 때문에 main 스레드의 모든 자식 스레드는 보통 값(5)의 우선순위를 가지고 탄생된됩니다. 하지만, 다음 메서드를 이용하면 우선순위 값을 바꿀 수 있습니다.

void setPriority(int newPriority) //newPriority로 스레드의 우선순위 값 변경

 


참고자료

https://code0123.tistory.com/172

 

[JAVA/자바] 스레드 생명 주기와 스케줄링

스레드 생명 주기와 스케줄링 스레드 상태 : 스레드는 JVM에 있어 생명체와 같다. 스레드는 태어나고, 실행하고, 잠자고, 대기하고, 종료하는 등 생명주기(life cycle)를 가진다. 그리고 생명 주기 동

code0123.tistory.com

https://velog.io/@tomato2532/JAVA-Thread-2-JVM-%EC%93%B0%EB%A0%88%EB%93%9C-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81

 

[JAVA] Thread 2 - JVM 쓰레드 스케줄링

JVM 내의 한 프로세스의 멀티쓰레드는 Concurrency하게 동작합니다. 여러 쓰레드를 동시성으로 멀티쓰레드를 동작시키기 때문에 쓰레드의 동작 상태에 대한 정의가 필요합니다. 각 쓰레드가 수행되

velog.io