위로
아래
스레드 생명 주기
스레드 생명 주기
- 생성 -> 준비 -> 실행 -> 보류(입출력 후) 또는 대기 -> 준비 반복
- 마지막엔 생성 -> 준비 -> 실행 -> 종료
특징
- 우선순위 개념이 없다
- start() 하면 준비 상태가 된다
- run() 하면 실행 상태가 된다
스레드의 상태 확인
- getState() 메소드 사용.
- 스레드 상태에 따라 다음 상수를 반환
상태 | 상수 | 설명 |
객체 생성 | NEW | 객체를 생성한 후 아직 시작하지 않은 상태 |
실행 대기 | RUNNABLE | 실행 준비가 된 상태 |
중지 | BLOCKED | 입출력 등 락(Lock)이 풀릴 때까지 기다리는 상태 |
WAITING | 다른 스레드가 통지할 때까지 기다리는 상태 | |
TIME_WAITING | 주어진 시간 동안 기다리는 상태 | |
종료 | TERMINATED | 실행을 마친 상태 |
Thread 클래스가 제공하는 상태 제어 메소드
- intrerrupt() : 실행 중인 스레드에 인터럽트를 걸어 중지시킨다
- join() : 주어진 시간이 지나거나 대응하는 스레드가 종료될 때까지 대기시킨다
- resume() : 중지 상태의 스레드를 실행 대기 상태로 전환시킨다
- static void sleep() : 주어진 시간 동안 중지한다.
- start() : 스레드를 실행 대기시킨다
- stop() : 스레드를 종료한다
- suspend() : 스레드를 중지한다
- yield() : 우선순위가 동일한 스레드에 실행을 양보한다.
스레드 종료
- 스레드는 run() 메소드를 마치면 보류 상태로 넘어간다.
- stop() 메소드를 사용하면 스레드를 불완전하게 종료한다.
- 스레드를 안전하게 종료하는 방법
- 반복문 조건 사용
- interrupt() 메소드
반복문 조건 사용 예시
더보기
public class StopThread extends Thread {
public boolean stop;
public void run() {
while(!stop) {
System.out.println("실행 중...");
try {
Thread.sleep(1);
} catch (InterruptedException e) {}
}
System.out.println("정상 종료");
}
}
public class StopDemo {
public static void main(String[] args) {
StopThread t = new StopThread();
t.start();
try {
Thread.sleep(3);
} catch (InterruptedException e) {}
t.stop = true;
}
}
interrupt() 메소드 예시
더보기
public class Interrupt1Demo {
public static void main(String[] args) {
Runnable task = () -> {
try {
while(true) {
System.out.println("실행 중...");
Thread.sleep(1);
}
} catch (InterruptedException e) {
System.out.println("인터럽트 : "+e.getMessage());
}
System.out.println("정상 종료");
};
Thread t = new Thread(task);
t.start();
try {
Thread.sleep(3);
} catch(InterruptedException e) {}
t.interrupt();
}
}
Join() 메소드
- 다른 스레드가 종료될 때까지 기다리게 하는 메소드
- 다른 스레드가 종료된 후에 스레드가 실행되어야 한다면 사용할 수 있다.
예시
더보기
//JoinThread 클래스 파일
public class JoinThread extends Thread{
int total;
public void run() {
for(int i = 1; i <=100 ; i++)
total += i;
}
}
public class JoinDemo {
public static void main(String[] args) {
JoinThread t = new JoinThread();
t.start();
// try {
// t.join();
// System.out.println("스레드 t가 끝날 때까지 대기...");
// } catch (InterruptedException e) {}
System.out.println("총합 : " + t.total);
}
}
// 숫자 더하는 거 안 기다리고 출력부터 해버린다.
public class JoinDemo {
public static void main(String[] args) {
JoinThread t = new JoinThread();
t.start();
try {
t.join();
System.out.println("스레드 t가 끝날 때까지 대기...");
} catch (InterruptedException e) {}
System.out.println("총합 : " + t.total);
}
}
// 숫자 더하는 거 다 기다렸다가 출력 스레드 실행
스레드 스케쥴링
스레드 스케줄링(thread scheduling)
- 스레드 개수가 CPU 코어 개수보다 많으면, 스레드에 CPU 타임슬롯을 어떤 방식으로 배정할지 결정해야 한다.
- 우선순위 방식 : 우선순위가 높은 스레드가 CPU 자원을 더 자주 사용할 수 있도록 하는 것
- 순환할당(round-robin) 방식 : 각 스레드가 차례대로 번갈아가면서 CPU 자원을 사용하는 것
우선순위 방식
- 낮은 순위부터 1~10이란 정수 부여, 기본 우선순위 값으로 모든 스레드게 5를 부여
- Thread 클래스가 제공하는 우선순위 상수
- MAX_PRIORITY : 최고 우선순위인 10을 나타내는 상수
- NORM_PRIORITY : 중간 우선순위인 5를 나타내는 상수
- MIN_PRIORITY : 최저 우선순위인 1을 나타내는 상수
예시
더보기
public class Counter extends Thread {
private int count = 0;
public Counter(String name) {
setName(name);
}
public void run() {
while(count++ < 5) {
System.out.print(getName() + " -> ");
try {
sleep(500);
} catch (InterruptedException e) {
}
}
}
}
public class PriorityDemo {
public static void main(String[] args) {
Counter c1 = new Counter("느긋한");
c1.setPriority(Thread.MIN_PRIORITY);
Counter c2 = new Counter("급한");
c2.setPriority(Thread.MAX_PRIORITY);
c1.start();
c2.start();
}
}
급한이 먼저 실행
데몬 스레드
데몬 스레드(daemon thread)
- 메인 스레드가 종료되면 함꼐 종료되는 보조 작업 스레드
- 우선순위가 가장 낮다
제공하는 메소드
- setDaemon(boolean status) : 데몬 스레드 여부를 설정한다. start() 메소드 호출 이전에 사용한다.
- isDaemon() : 데몬 스레드 여부를 반환 (boolean)
예시
더보기
//데몬 스레드가 아닐 시
public class DaemonDemo {
public static void main(String[] args) {
Runnable task = () -> {
for(int i=0 ; i<3 ; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println(Thread.currentThread().getName());
}
};
Thread t1 = new Thread(task, "작업 스레드");
//t1.setDaemon(true);
t1.start();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {}
System.out.println("메인 스레드가 끝났습니다.");
}
}
//데몬 스레드가 있을 시
public class DaemonDemo {
public static void main(String[] args) {
Runnable task = () -> {
for(int i=0 ; i<3 ; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println(Thread.currentThread().getName());
}
};
Thread t1 = new Thread(task, "작업 스레드");
t1.setDaemon(true);
t1.start();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {}
System.out.println("메인 스레드가 끝났습니다.");
}
}