이번에는 스레드 상태에 대해서 알아보도록 하겠습니다.
스레드 프로그래밍을 진행하다보면 동기화/비동기화 뿐만 아니라 스레드의 행동을 직접 제어해야 할 경우가 생깁니다.
1000장의 문서를 복사해야한다고 가정합니다.
공유된 프린터는 1개 밖에 없는데, 이 때 1000장을 전부 복사하는 동안 혼자서 쓸 수 없을 겁니다.
다른 사람들도 프린터를 사용해야 하는 경우가 분명 생길거에요.
그럴 때, 100장씩 복사를 하도록 하고, 그 때마다 다른 사람들이 사용하도록 통제할 수도 있을거에요.
이처럼 스레드도 상태를 제어해야 할 필요성이 있는데, 제어를 하기 전에 해당 스레드의 상태를 알아야 합니다.
그러기 위해서는 getState() 메서드를 사용하여 상태를 확인합니다.
□ 스레드 상태
· 스레드는 start() 하게 되면 일반적으로 다음과 같은 상태로 진행 됩니다.
· 경우에 따라서 스레드는 실행 상태에서 실행 대기 상태로 가지 않을 수도 있습니다.
· 실행 상태에서 일시 정지 상태로 가기도 하는데, 일시 정지 상태는 스레드가 실행할 수 없는 상태입니다.
· 스레드가 다시 실행 상태로 가기 위해서는 일시 정지 상태에서 실행 대기 상태로 가야합니다.
이처럼 프로그래밍 하면서 스레드의 상태를 알 수 있도록 해주는 메소드는 getState() 입니다.
getState()의 스레드 상태에 따른 Thread.State 열거 상수가 있는데 열거 상수는 다음의 표와 같습니다.
상태 | 열거 상수 | 설명 |
객체 생성 | NEW | 스레드 객체가 생성, 아직 start() 메소드가 호출되지 않은 상태 |
실행 대기 | RUNNABLE | 실행 상태로 언제든지 갈 수 있는 상태 |
일시 정지 | WAITING | 다른 스레드가 통지할 때까지 기다리는 상태 |
TIMED_WAITING | 주어진 시간 동안 기다리는 상태 | |
BLOCKED | 사용하고자 하는 객체의 락이 풀릴 때까지 기다리는 상태 | |
종료 | TERMINATED | 실행을 마친 상태 |
이제 프로그래밍을 통해 스레드의 상태를 직접 확인해 봅시다.
이 예제는 스레드의 상태를 출력해주며, 생성자 매개값으로 받은 타겟 스레드의 상태를 0.5초 주기로 출력 해주는 클래스 입니다.
StatePrintThread.java - 타겟 스레드의 상태를 출력하는 스레드
package thread_state;
public class StatePrintThread extends Thread {
private Thread targetThread;
public StatePrintThread(Thread targetThread) {
this.targetThread = targetThread;
}
@Override
public void run() {
while(true) {
Thread.State state = targetThread.getState(); // 스레드 상태 얻기
System.out.println("타겟 스레드 상태: " + state);
// 객체 생성 상태일 경우 실행 대기 상태로 만듬
if(state == Thread.State.NEW) {
targetThread.start();
}
// 종료 상태일 경우 while문을 종료함
if(state == Thread.State.TERMINATED) {
break;
}
try {
Thread.sleep(500);
} catch(Exception e) {}
}
}
}
다음은 타겟 스레드 클래스입니다.
10억 번 루핑을 돌게 해서 RUNNABLE 상태를 유지하고, sleep() 메소드를 호출해서 1.5초간 TIMED_WAITING 상태를 유지합니다.
또한 다시 10억 번 루핑을 돌게 해서 RUNNABLE 상태를 유지합니다.
TargetThread.java - 타겟 스레드
package thread_state;
public class TargetThread extends Thread {
@Override
public void run() {
for(long i=0; i<1000000000; i++) {}
try {
Thread.sleep(1500);
} catch(Exception e) {}
for(long i=0; i<1000000000; i++) {}
}
}
TargetThread가 객체로 생성되면 NEW 상태를 가지고, run() 메소드가 종료되면 TERMINATED 상태가 되므로 결국 다음과 같은 상태로 변합니다.
NEW -> RUNNABLE -> TIMED_WAITING -> RUNNABLE -> TERMINATED
다음은 StatePrintThread를 생성해서 매개값으로 전달받은 TargetThread의 상태를 출력하는 클래스입니다.
ThreadStateExample.java - 실행 클래스
package thread_state;
public class ThreadStateExample {
public static void main(String[] args) {
StatePrintThread statePrintThread =
new StatePrintThread(new TargetThread());
statePrintThread.start();
}
}
실행을 하면
타겟 스레드 상태: NEW
타겟 스레드 상태: RUNNABLE
타겟 스레드 상태: RUNNABLE
타겟 스레드 상태: TIMED_WAITING
타겟 스레드 상태: TIMED_WAITING
타겟 스레드 상태: TIMED_WAITING
타겟 스레드 상태: RUNNABLE
타겟 스레드 상태: RUNNABLE
타겟 스레드 상태: RUNNABLE
타겟 스레드 상태: TERMINATED
이와 같은 실행 결과를 확인할 수 있다.. 고 이것이 자바다에 나와 있습니다.
저는 다음과 같은 상태변화만 확인할 수 있었습니다.
타겟 스레드 상태: NEW
타겟 스레드 상태: TIMED_WAITING
타겟 스레드 상태: TIMED_WAITING
타겟 스레드 상태: TIMED_WAITING
타겟 스레드 상태: RUNNABLE
타겟 스레드 상태: TERMINATED
제가 자세하게 안다면 이와 같은 현상에 대해서 자세하게 알 수 있을텐데 아직 많이 부족하여 잘 모르겠네요..
첫 번째 10억 번 루핑도는 부분에서 상태가 잡히지 않는 것 같습니다.
출력을 찍어보면 정상적으로 되는 것 같은데 해당 상태가 RUNNABLE이 맞다고 생각하는데 첫 번째 루핑 넘어간 다음 sleep()으로 바로 넘어가서 TIMED_WAITING이 출력되네요.
시스템 환경을 다양하게해서 확인해 봐야 할 것 같습니다.
'프로그래밍 언어 > Java' 카테고리의 다른 글
Java - 데몬 스레드 (Daemon Thread) (0) | 2019.08.16 |
---|---|
Java - 스레드 상태 제어 (Thread State Control) part 3 (2) | 2019.08.16 |
Java - 스레드 상태 제어 (Thread State Control) part 2 (0) | 2019.08.16 |
Java - 스레드 상태 제어 (Thread State Control) part 1 (2) | 2019.08.11 |
Java 멀티 스레드 - Synchronized(동기화) (0) | 2019.08.10 |