스레드 인터럽트 메커니즘
Java에서 스레드는 외부에서 강제로 중지되지 않으며 자발적으로 중단해야 합니다. Thread.stop()과 같은 메서드는 폐기되었으며, 대신 협력적 인터럽트 메커니즘이 도입되었습니다. 스레드 객체의 interrupt() 호출은 인터럽트 플래그를 설정하고, 대상 스레드가 이 상태를 주기적으로 확인하여 작업을 종료합니다.
인터럽트 API 메서드
void interrupt(): 스레드의 인터럽트 상태 설정boolean isInterrupted(): 스레드의 인터럽트 상태 확인 (상태 변경 없음)static boolean interrupted(): 현재 스레드의 인터럽트 상태 반환 후 초기화
실행 중인 스레드 중지 방법
volatile 변수 활용:
public class InterruptExample {
private static volatile boolean stopRequested = false;
public static void main(String[] args) {
new Thread(() -> {
while (!stopRequested) {
System.out.println("실행 중");
}
System.out.println("종료: 플래그 변경 감지");
}).start();
new Thread(() -> {
try { Thread.sleep(20); }
catch (InterruptedException e) {}
stopRequested = true;
}).start();
}
}
AtomicBoolean 활용:
public class AtomicInterrupt {
private static final AtomicBoolean atomicFlag = new AtomicBoolean(false);
public static void main(String[] args) {
new Thread(() -> {
while (!atomicFlag.get()) {
System.out.println("동작 중");
}
System.out.println("중단: 원자적 플래그 변경");
}).start();
new Thread(() -> {
try { Thread.sleep(20); }
catch (InterruptedException e) {}
atomicFlag.set(true);
}).start();
}
}
인터럽트 API 직접 사용:
public class DirectInterrupt {
public static void main(String[] args) {
Thread worker = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("작업 수행");
}
System.out.println("인터럽트 감지");
});
worker.start();
new Thread(() -> {
try { Thread.sleep(20); }
catch (InterruptedException e) {}
worker.interrupt();
}).start();
}
}
인터럽트 주의사항
sleep() 중 인터럽트 발생 시:
public class SleepInterrupt {
public static void main(String[] args) {
Thread t = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(200);
System.out.println("작업 계속");
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 플래그 재설정
}
}
System.out.println("정상 종료");
});
t.start();
t.interrupt();
}
}
LockSupport 동기화
LockSupport는 스레드 블로킹 기본 구현체로, park()과 unpark() 메서드를 제공합니다.
기본 사용법
import java.util.concurrent.locks.LockSupport;
public class ParkExample {
public static void main(String[] args) {
Thread worker = new Thread(() -> {
System.out.println("진입");
LockSupport.park();
System.out.println("재개");
});
worker.start();
LockSupport.unpark(worker); // 즉시 재개
}
}
실행 순서 유연성
public class OrderExample {
public static void main(String[] args) {
Thread worker = new Thread(() -> {
try { Thread.sleep(1000); }
catch (InterruptedException e) {}
System.out.println("park 호출");
LockSupport.park();
System.out.println("실행 완료");
});
worker.start();
LockSupport.unpark(worker); // 선행 unpark
}
}
Permit 동작 원리
- unpark(): permit 설정 (최대 1개)
- park(): permit 소모 (있으면 통과, 없면 대기)
- 중복 unpark()은 permit 누적되지 않음