[Java] 스레드 상태
스레드 객체를 생성하고, start() 메소드를 호출하면 곧바로 스레드가 실행되는 것처럼 보이지만 사실은 실행 대기 상태가 된다. 실행 대기 상태란 아직 스케줄링이 되지 않아서 실행을 기다리고 있는 상태를 말한다. 실행 대기 상태에 있는 스레드 중에서 스레드 스케줄링으로 선택된 스레드가 비로서 CPU를 점유하고 run() 메소드를 실행한다. 이때를 실행(Running) 상태라고 한다. 실행 상태의 스레드는 run() 메소드를 모두 실행하기 전에 스레드 스케줄링에 의해 다시 실행 대기 상태로 돌아갈 수 있다. 그리고 실행 대기 상태에 있는 다른 스레드가 선택되어 실행 상태가 된다. 이렇게 스레드는 실행 대기 상태와 실행 상태를 번강아가면서 자신의 run() 메소드를 조금씩 실행한다. 실행 상태에서 run() 메소드가 종료되면, 더이상 실행할 코드가 없기 때문에 스레드의 실행은 멈추게 된다. 이 상태를 종료 상태라고 한다.
경우에 따라서 스레드는 실행 상태에서 실행 대기 상태로 가지 않을 수도 있다. 실행 상태에서 일시 정지 상태로 가기도 하는데, 일시 정지 상태는 스레드가 실행할 수 없는 상태이다. 일시 정지 상태는 WAITING, TIMED_WAITING, BLOCKED 가 있는데, 일시 정지 상태가 되는 이유는 나중에 설명하도록 하고, 스레드가 다시 실행 상태로 가기 위해서는 일시 정지 상태에서 실행 대기 상태로 가야 한다는 것만 알아두자.
이러한 스레드의 상태를 코드에서 확인할 수 있도록 하기 위해 자바 5부터 Thread 클래스에 getState() 메소드가 추가되었다. getState() 메소드는 다음 표처럼 스레드 상태에 따라서 Thread.State 열거 상수를 리턴한다.
상태 | 열거 상수 | 설명 |
객체 생성 | NEW | 스레드 객체가 생성, 아직 start() 메소드가 호출되지 않은 상태 |
실행 대기 | RUNNABLE | 실행 상태로 언제든지 갈 수 있는 상태 |
일시 정지 | WAITING | 다른 스레드가 통지할 때까지 기다리는 상태 |
TIMED_WAITING | 주어진 시간 동안 기다리는 상태 | |
BLOCKED | 사용하고자 하는 객체의 락이 풀릴 때까지 기다리는 상태 | |
종료 | TERMINATED | 실행을 마친 상태 |
다음은 스레드의 상태를 출력하는 StatePrintThread 클래스이다. 생성자 매개값으로 받은 타겟 스레드의 상태를 0.5초 주기로 출력한다.
// StatePrintThread.java -- 타겟 스레드의 상태를 출력하는 스레드
public class StatePrintThread extends Thread {
private Thread targetThread;
public StatePrintThread(Thread targetThread) {
this.targetThread = targetThread;
}
public void run() {
while(true) {
Thread.State state = targetThread.getState(); // 스레드 상태 얻기
System.out.println("타겟 스레드 상태: " + state);
if(state == Thread.State.NEW) { // 객체 생성 상태일 경우 실행 대기 상태로 만듦
targetThread.start();
}
if(state == Thread.State.TERMINATED) { // 종료 상태일 경우 while문을 종료함
break;
}
try {
// 0.5 초간 일시 정지
Thread.sleep(500);
} catch(Exception e) {}
}
}
}
다음은 타겟 스레드 클래스이다. 3라인에서 10억 번 루핑을 돌게 해서 RUNNABLE 상태를 유지하고 7라인에서 sleep() 메소드를 호출해서 1.5초간 TIMED_WAITING 상태를 유지한다. 그리고 10라인에서는 다시 10억 번 루핑을 돌게 해서 RUNNABLE 상태를 유지한다.
// TargetThread.java -- 타겟 스레드
public class TargetThread extends Thread {
public void run() {
for(long i=0; i<1000000000; i++) {}
try {
// 1.5 초간 정지
Thread.sleep(1500);
} catch(Exception e) {}
for(long i=0; i<1000000000; i++) {}
}
}
TargetThread가 객체로 생성되면 NEW 상태를 가지고, run() 메소드가 종료되면 TERMINATED 상태가 되므로 결국 다음과 같은 상태로 변한다.
NEW -> RUNNABLE -> TIMED_WAITING -> RUNNALBE -> TERMINATED
다음은 StatePrintThread를 생성해서 매개값으로 전달받은 TargetThread의 상태를 출력하도록 작성된 실행 클래스이다.
// ThreadStateExample.java -- 실행 클래스
public class TheradStateExample {
public static void main(String[] args) {
StatePrintThread statePrintThread = new StatePrintThread(new TargetThread());
statePrintThread.start();
}
}