본문 바로가기
java/개념

스레드 생명 주기와 스케줄링

by unhyepnhj 2024. 11. 28.

스레드 상태

 

스레드는 생명 주기(life cycle)동안 여러 상태의 변이(NEW, RUNNABLE, TIMED_WAITING, BLOCK, WAITING, TERMINATED)를 거친다.


1. NEW(생성): 스레드가 생성되었으나 아직 실행할 준비가 되지 않은 상태

new Thread()에 의해 NEW 상태의 스레드가 생성됐을 때 이 스레드는 스케줄링되지 않아 실행될 수 없는 상태이다. 이때 스케줄링이란 JVM이 RUNNABLE 상태의 스레드 중 하나를 선택하여 실행시키는 것이며, start() 메소드가 호출되면 스레드는 RUNNABLE 상태로 전환된다.

 

2. RUNNABLE(준비): 스레드가 현재 실행되고 있거나 실행 준비되어 스케줄링을 기다리는 상태

start() 메소드가 호출되어 NEW에서 RUNNABLE로 변이하면 스레드는 비로소 실행될 수 있다. JVM은 RUNNABLE 상태에 있는 스레드 중 하나를 선택하고 실행시키며(스케줄링), 처음으로 스케줄링되는 스레드는 run() 메소드의 첫 번째 줄부터 실행을 시작한다. 스레드 스케줄링 시 JVM은 우선순위가 높은 스레드를 먼저 선택하고, 우선순위가 동일한 스레드가 여러 개 존재하면 round robin한다.

 

실행 중인 스레드가 yield()를 호출하면, JVM은 현재 실행 중인 스레드(yield()를 호출한 스레드)를 즉각 RUNNABLE 상태로 변경하고 다시 스케줄링을 실시한다. 만약 우선순위가 더 높거나 같은 다른 스레드가 없으면 이 스레드가 다시 스케줄링된다.

 

3. TIMED_WAITING(대기): 스레드가 sleep(long n)을 호출하여 n밀리초 동안 정지한 상태

실행 중인 스레드가 sleep(ms)을 호출하면 ms 밀리초 시간만큼 "잠을 자게" 되고, JVM은 이 스레드를 TIMED_WAITING 상태로 변경한 뒤 스케줄링을 실시한다. 이 스레드는 ms 밀리초 후 "깨어나" RUNNABLE 상태가 된다.

 

4. BLOCK(일시 중단)

화면 출력이나 키보드 입출력 등 스레드가 I/O 작업을 하게 되면 JVM이 스레드를 즉각 중지하며 BLOCK 상태로 전환한다. BLOCK 상태의 스레드는 I/O 작업이 완료될 때까지 스케줄링 없이 대기하고, I/O 작업이 완료되면 스레드는 자동으로 RUNNABLE 상태로 전환된다.

 

5. WAITING(대기)

스레드가 어떤 객체 a에 대해 a.wait()을 호출하면 다른 스레드가 a.notify(), a.notifyAll()을 호출할 때까지 무한정 대기한다. 대기 시간을 전달받지 않는다는 점에서 TIMED_WAITING 상태와 다르다. 이때 객체 a를 동기화 객체라 하며, 모든 객체는 java.lang.Object를 상속받고 wait() 메소드는 java.lang.Object 클래스의 멤버이므로 모든 객체는 동기화 객체가 될 수 있다. 첫 번째 스레드가 a.wait()을 호출하여 대기 중일 때 다른 스레드가 a.notify()나 a.notifyAll()을 호출하면 첫 번째 스레드는 RUNNABLE 상태로 복귀하게 된다.

 

6. TERMINATED(종료)

실행 중인 스레드가 종료되면 TERMINATED 상태가 되며, JVM은 다른 스레드의 스케줄링을 시작한다. TERMINATED 상태인 스레드는 더 이상 다른 상태로 변이할 수 없다(RUNNABLE 상태로도 변할 수 없으므로 다시 실행될 수 없다).


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

 

JVM은 우선순위에 기반해 스레드를 스케줄링한다. 자바 스레드의 우선순위 체계는 아래와 같은데,

최대 우선순위(MAX_PRIORITY) = 10
최소 우선순위(MIN_PRIORITY) = 1
보통 우선순위(NORMAL_PRIORITY) = 5

가장 높은 우선순위의 스레드가 먼저 실행되며, 우선순위가 같을 경우 돌아가면서 실행(round-robin)된다.

 

자바 응용프로그램이 실행될 때 처음으로 생성되는 main() 스레드는 NORMAL_PRIORITY(5)의 우선순위로 생성되므로 main() 스레드의 모든 자식 스레드 또한 5의 우선순위를 가진다. 하지만, setPriority(int newPriority) 메소드를 사용해 우선순위를 변경할 수 있다.

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

main()을 실행하는 main 스레드

 

JVM은 자바 응용프로그램을 실행하기 직전 사용자 스레드인 main 스레드를 하나 만들어 이 스레드가 main() 메소드를 실행하도록 한다. main 스레드의 실행 시작 주소는 main() 메소드의 첫 코드이다. 따라서 자바 응용프로그램의 main() 메소드가 실행되는 순간 main 스레드와 가비지 컬렉션 스레드, 2개의 스레드가 존재하게 된다. 

'java > 개념' 카테고리의 다른 글

스레드 동기화(Thread Synchronization)  (0) 2024.11.28
스레드 종료  (0) 2024.11.28
스레드 만들기  (0) 2024.11.19
자바의 멀티스레딩  (0) 2024.11.19
멀티태스킹  (0) 2024.11.19