Thread
- 프로그램 내에서 독립적으로 실행되는 작업 흐름(execution flow)
- 멀티스레딩을 사용하면 여러 작업을 동시에 수행할 수 있기 때문에 프로그램의 성능이 향상됨
생성 방법
- Thread 클래스 상속
class MyThread extends Thread {
public void run() { // 반드시 run() 메서드를 오버라이딩 해야 함
System.out.println("Thread 실행 중...");
}
}
public class ThreadExample {
public static void main(String\[\] args) {
MyThread thread = new MyThread(); // 스레드 객체 생성
thread.start(); // 스레드 실행
}
}
- strat() 메소드를 호출하면 JVM이 run() 메소드 실행
- start()를 여러 번 호출하면 IllegalThreadStateException 발생
run을 무조건 오버라이딩 해야 하는 이유
@Override
public void run() {
Runnable task = holder.task;
if (task != null) {
Object bindings = scopedValueBindings();
runWith(bindings, task);
}
}
- 오버라이딩 하지 않으면 holder(실행 가능한 작업을 보관하고 있는 객체) 내의 task가 비어 있기 때문
- Runnable 인터페이스 구현
class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable 실행 중...");
}
}
public class ThreadExample {
public static void main(String\[\] args) {
Thread thread = new Thread(new MyRunnable()); // Runnable을 Thread에 전달
thread.start();
}
}
- Runnable을 사용하면 다중 상속 문제를 피할 수 있음 -> Thread를 직접 상속하는 대신 Runnable을 구현하는 것이 권장됨
주요 개념
- 스레드의 우선 순위(Priority) : OS 스케줄러의 정책에 따라 적용될 수도 있고 안될 수도 있음
- MIN_PRIORITY = 1 (가장 낮음)
- NORM_PRIORITY = 5 (기본값)
- MAX_PRIORITY = 10 (가장 높음)
- Deamon Thread(데몬 스레드)
- 백그라운드에서 실행되며, 다른 모든 일반 스레드(Non-Daemon Thread)가 종료되면 자동 종료됨
- 프로그램이 종료될 때 강제로 정리할 필요 없이 자동으로 종료
- Thread.State(스레드 상태)
상태 |
설명 |
NEW |
start()를 호출하기 전 상태) |
RUNNABLE |
실행 가능한 상태(CPU가 실행시킬 수 있음) |
BLOCKED |
다른 스레드가 락을 가지고 있어서 대기중 |
WAITING |
특정 조건이 충족될 때까지 기다리는 상태 |
TIMED_WAITING |
일정 시간이 지나면 깨어나는 상태 |
TERMINATED |
스레드 실행이 종료됨 |
- Synchronized(스레드 동기화)
- 멀티스레드 환경에서 여러 스레드가 동시에 같은 자원에 접근하면 충돌이 발생할 수 있기 때문에 임계 영역(Cirtical Section)을 보호하기 위한 것
- synchronized를 사용하면 하나의 스레드만 해당 메소드에 접근 가능하므로 안전함
- 스레드 제어 메소드
메소드 |
설명 |
start() |
새로운 스레드 실행 |
run() |
직접 호출하면 멀티스레딩 효과 X(start()를 사용해야 함) |
sleep(ms) |
지정한 시간 동안 스레드 일시 정지 |
join() |
현재 스레드가 종료될 때까지 기다림 |
interrupt() |
실행 중인 스레드 중단 요청 |
isAlive() |
스레드가 실행 중인지 확인 |