728x90
import static util.MyLogger.log;
import static util.ThreadUtils.sleep;
public class ThreadStopMainV1 {
public static void main(String[] args) {
MyTask task = new MyTask();
Thread thread = new Thread(task, "work");
thread.start();
sleep(4000);
log("작업 중단 지시 runFlag=false");
task.runFlag = false;
}
static class MyTask implements Runnable {
volatile boolean runFlag = true;
@Override
public void run() {
while (runFlag) {
log("작업 중");
sleep(3000);
}
log("자원 정리");
log("작업 종료");
}
}
}
work 스레드는 runFlag 의 조건이 false 로 변한 것을 확인하고, while문을 빠져 나가면서 작업을 종료한다.
인터럽트를 사용하면, WAITING, TIMED_WAITING 같은 대기 상태의 스레드를 직접 깨워서, 작동하는 RUNNABLE 상태로 만들 수 있다.
@Override
public void run() {
try {
while (true) {
log("작업 중");
Thread.sleep(3000);
}
}
catch (InterruptedException e) {
log("work 스레드 인터럽트 상태2 = " + Thread.currentThread().isInterrupted());
log("interrupt message=" + e.getMessage());
log("state=" + Thread.currentThread().getState());
}
log("자원 정리");
log("작업 종료");
}
이때 인터럽트를 받은 스레드는 대기 상태에서 깨어나 RUNNABLE 상태가 되고, 코드를 정상 수행한다.
work 스레드는 인터럽트 상태가 되었고, 인터럽트 상태이기 때문에 인터럽트 예외가 발생한다.
import static util.MyLogger.log;
import static util.ThreadUtils.sleep;
public class ThreadStopMainV4 {
public static void main(String[] args) {
MyTask task = new MyTask();
Thread thread = new Thread(task, "work");
thread.start();
sleep(100); //시간을 줄임
log("작업 중단 지시 - thread.interrupt()");
thread.interrupt();
log("work 스레드 인터럽트 상태1 = " + thread.isInterrupted());
}
static class MyTask implements Runnable {
@Override
public void run() {
while (!Thread.interrupted()) { //인터럽트 상태 변경O
log("작업 중");
}
log("work 스레드 인터럽트 상태2 = " +Thread.currentThread().isInterrupted());
try {
log("자원 정리 시도");
Thread.sleep(1000);
log("자원 정리 완료");
}
catch (InterruptedException e) {
log("자원 정리 실패 - 자원 정리 중 인터럽트 발생");
log("work 스레드 인터럽트 상태3 = " +
Thread.currentThread().isInterrupted());
}
log("작업 종료");
}
}
}
Thread.interrupted() 를 호출했을 때 스레드가 인터럽트 상태 (true) 라면 , true 반환, 해당 스레드의 인터럽트 상태를 false로 변경한다. 결과적으로 while문을 탈출하는 시점에, 스레드의 인터럽트 상태도 false 로 변경된다.
work 스레드는 이후에 자원을 정리하는 코드를 실행하는데, 이때 인터럽트의 상태는 false 이므로 인터럽트가 발생 하는 sleep() 과 같은 코드를 수행해도 인터럽트가 발생하지 않는다. 이후에 자원을 정상적으로 잘 정리하는 것을 확인 할 수 있다. 자바는 인터럽트 예외가 한 번 발생하면, 스레드의 인터럽트 상태를 다시 정상( false ) 으로 돌린다.
스레드의 인터럽트 상태를 정상으로 돌리지 않으면 이후에도 계속 인터럽트가 발생하게 된다. ** 인터럽트의 목적을 달성하면 인터럽트 상태를 다시 정상으로 돌려두어야 한다
728x90
'운영체제' 카테고리의 다른 글
Synchronized (0) | 2024.12.15 |
---|---|
Volatile - 메모리가시성 (0) | 2024.12.15 |
Thread - Join (0) | 2024.12.14 |
체크 예외 재정의 (1) | 2024.11.29 |
Thread 생명 주기 - 코드 (0) | 2024.11.29 |