Unit 6.3 — 인터럽트(Interrupt) 메커니즘

Psj·2026년 5월 26일

F-lab

목록 보기
143/230

Unit 6.3 — 인터럽트(Interrupt) 메커니즘

F-LAB JAVA · 4주차 · Phase 6 · 스레드 간 협력


📌 학습 목표

이 Unit을 끝내면 다음을 답할 수 있어야 한다.

  • 인터럽트 (Interrupt) 의 정의는?
  • 인터럽트가 강제 종료가 아닌 이유는?
  • interrupt() / isInterrupted() / interrupted() 의 차이는?
  • interrupted() 가 static 이고 플래그를 리셋 하는 이유는?
  • InterruptedException 발생 시 플래그 상태는?
  • 인터럽트 플래그 복원 의 필요성은?
  • 협력적 종료 패턴 은?
  • 즉각 종료 패턴 (while (!Thread.interrupted())) 은?
  • 인터럽트 무시의 위험 은?

🎯 핵심 한 문장

인터럽트 (Interrupt) 는 한 스레드가 다른 스레드에게 "중단을 요청" 하는 협력적 메커니즘이며, 강제 종료가 아니라 인터럽트 플래그를 설정하는 신호일 뿐이다.
interrupt() 는 대상 스레드의 인터럽트 플래그를 true 로 설정하고, isInterrupted() 는 플래그를 확인 (변경 X), interrupted() 는 static 메서드로 현재 스레드의 플래그를 확인한 후 false 로 리셋한다.
wait()·sleep()·join() 등 블로킹 메서드는 인터럽트되면 InterruptedException 을 던지면서 플래그를 false 로 리셋 하므로, 인터럽트 정보를 유지하려면 Thread.currentThread().interrupt()플래그를 복원 해야 한다.
인터럽트는 강제 종료가 아니므로 스레드가 플래그를 확인하고 스스로 종료 해야 하며 (협력적 종료), 무한 루프에서는 while (!Thread.currentThread().isInterrupted()) 패턴으로 인터럽트 시 깔끔히 빠져나온다.
인터럽트를 무시하면 (catch 후 아무것도 안 함) 종료 신호가 사라져 스레드가 멈추지 않으므로, 최소한 플래그를 복원하거나 종료해야 한다.

비유 — 어깨 두드리기

인터럽트 = "그만하라" 어깨 두드리기:

interrupt() = 어깨 두드림 (요청):
  - "이제 그만 하는 게 어때?"
  - 강제 X (요청일 뿐)
  - 플래그 설정 (신호)

스레드의 선택 (협력적):
  - 플래그 확인 → 스스로 종료
  - 또는 무시 (계속 — 위험)

isInterrupted() = 어깨 봤나 확인:
  - 두드림 확인 (플래그 그대로)

interrupted() = 확인 + 잊기 (static):
  - 두드림 확인 + 리셋
  - 현재 스레드만

InterruptedException = 자다가 두드림:
  - sleep/wait 중 두드리면
  - 깜짝 깨어남 (예외)
  - 두드림 흔적 지움 (플래그 리셋)
  - → 다시 두드린 척 (복원) 필요

협력적 종료:
  - 두드리면 스스로 정리하고 나감
  - 강제로 끌어내지 X (안전)

→ 인터럽트 = 중단 요청 (강제 X), 플래그 신호, 협력적 종료.


🧭 9개 섹션 로드맵

1. 인터럽트의 정의
2. 강제 종료가 아닌 이유
3. interrupt / isInterrupted / interrupted
4. interrupted()의 static과 리셋
5. InterruptedException과 플래그
6. 플래그 복원
7. 협력적 종료 패턴
8. 즉각 종료 패턴
9. 면접 + 자기 점검

1️⃣ 인터럽트의 정의

1.1 인터럽트란

인터럽트 (Interrupt):

  한 스레드가 다른 스레드에게
  "중단을 요청" 하는 협력적 메커니즘.

특징:
  - 요청일 뿐 (강제 X)
  - 플래그 설정
  - 스레드가 확인하고 처리

1.2 인터럽트 플래그

인터럽트 플래그:

  각 스레드가 가진 boolean 상태.
  - interrupt(): true 설정
  - isInterrupted(): 확인
  - interrupted(): 확인 + 리셋

  → 인터럽트 요청 표시

1.3 기본 사용

Thread worker = new Thread(() -> {
    while (!Thread.currentThread().isInterrupted()) {
        doWork();   // 인터럽트 안 됐으면 계속
    }
    cleanup();   // 인터럽트 시 정리
});
worker.start();

worker.interrupt();   // 중단 요청 (플래그 설정)

1.4 용도

인터럽트 용도:

  - 스레드 종료 요청
  - 작업 취소
  - 타임아웃
  - graceful shutdown

핵심:
  - 협력적 중단
  - 강제 X

1.5 ILIC 의 맥락

@Service
public class InterruptBasics {
    
    private Thread worker;
    
    public void startWorker() {
        worker = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                processNextShipment();   // 작업
            }
            log.info("Worker stopped gracefully");
            cleanup();
        });
        worker.start();
    }
    
    public void stopWorker() {
        if (worker != null) {
            worker.interrupt();   // 중단 요청
        }
    }
    
    private void processNextShipment() { }
    private void cleanup() { }
}

1.6 자기 점검 답변

인터럽트의 정의는?

:
1. 정의:

  • 중단 요청
  • 협력적 메커니즘
  1. 플래그:

    • boolean 상태
    • interrupt 로 설정
  2. 특징:

    • 요청 (강제 X)
    • 확인하고 처리
  3. 용도:

    • 종료, 취소, 타임아웃

2️⃣ 강제 종료가 아닌 이유

2.1 협력적 중단

인터럽트는 협력적:

  강제 종료 X.
  - 플래그만 설정
  - 스레드가 확인하고 스스로 종료
  - 무시도 가능 (위험)

이유:
  - 안전 (자원 정리)
  - 일관성 (중간 상태 방지)

2.2 강제 종료의 위험

강제 종료 (stop()) 의 위험:

  Thread.stop() (deprecated):
    - 즉시 강제 종료
    - 락 즉시 반납 (중간 상태)
    - 자원 정리 X
    - 데이터 손상

  → deprecated (사용 금지)
  → 인터럽트 (협력적) 권장

2.3 협력적의 장점

협력적 중단의 장점:

  - 안전한 종료 시점 선택
  - 자원 정리 (cleanup)
  - 일관성 유지
  - 데이터 손상 방지

스레드가:
  - 안전한 지점에서
  - 정리하고
  - 종료

2.4 stop() vs interrupt()

// ❌ stop() — 강제 (deprecated)
worker.stop();   // 즉시 종료 (위험)
// 중간 상태, 자원 누수

// ✓ interrupt() — 협력적
worker.interrupt();   // 요청
// 스레드가:
while (!Thread.currentThread().isInterrupted()) {
    work();
}
cleanup();   // 안전하게 정리

2.5 무시 가능

// 인터럽트 무시 (가능하지만 위험)
Thread worker = new Thread(() -> {
    while (true) {   // 플래그 확인 X
        doWork();
        // 인터럽트 무시 → 영원히
    }
});
worker.start();
worker.interrupt();   // 효과 없음 (무시됨)

// → 플래그 확인 필요

2.6 ILIC 의 맥락

@Service
public class CooperativeInterrupt {
    
    // ✓ 협력적 종료
    public void startCooperative() {
        Thread worker = new Thread(() -> {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    Shipment shipment = takeShipment();
                    process(shipment);   // 진행 중 작업 완료
                }
            } finally {
                // 안전한 정리
                flushPendingData();
                closeResources();
                log.info("Worker cleaned up");
            }
        });
        worker.start();
    }
    
    private Shipment takeShipment() { return null; }
    private void process(Shipment s) { }
    private void flushPendingData() { }
    private void closeResources() { }
}

2.7 자기 점검 답변

인터럽트가 강제 종료가 아닌 이유는?

:
1. 협력적:

  • 플래그만 설정
  • 스레드가 스스로 종료
  1. 강제 위험:

    • stop() deprecated
    • 중간 상태, 손상
  2. 장점:

    • 안전한 시점
    • 자원 정리
  3. 무시 가능:

    • 플래그 확인 필요

3️⃣ interrupt / isInterrupted / interrupted

3.1 세 메서드

// 1. interrupt() — 인터럽트 요청 (인스턴스)
void interrupt();

// 2. isInterrupted() — 플래그 확인 (인스턴스)
boolean isInterrupted();

// 3. interrupted() — 확인 + 리셋 (static)
static boolean interrupted();

3.2 interrupt()

interrupt():

  대상 스레드의 인터럽트 플래그를 true.

  worker.interrupt();
  → worker 의 플래그 설정

  - 인스턴스 메서드
  - 대상 지정

3.3 isInterrupted()

isInterrupted():

  대상 스레드의 플래그 확인.
  - 플래그 변경 X (그대로)
  - 인스턴스 메서드

  worker.isInterrupted();
  → worker 의 플래그 반환

3.4 interrupted()

interrupted():

  현재 스레드의 플래그 확인 + 리셋.
  - 확인 후 false 로 리셋
  - static 메서드 (현재 스레드)

  Thread.interrupted();
  → 현재 스레드 플래그 확인 + 리셋

3.5 비교

메서드대상플래그 변경타입
interrupt()지정 스레드true 설정인스턴스
isInterrupted()지정 스레드변경 X인스턴스
interrupted()현재 스레드확인 후 리셋static

3.6 ILIC 의 맥락

public class InterruptMethods {
    
    public void demonstrate() {
        Thread worker = new Thread(() -> {
            // isInterrupted — 확인 (리셋 X)
            while (!Thread.currentThread().isInterrupted()) {
                doWork();
            }
            // 플래그 그대로 (다음 확인도 true)
        });
        worker.start();
        
        // interrupt — 요청
        worker.interrupt();   // worker 플래그 설정
        
        // isInterrupted — 외부 확인
        boolean interrupted = worker.isInterrupted();   // 확인 (그대로)
    }
    
    public void interruptedExample() {
        // interrupted — 현재 스레드 확인 + 리셋
        if (Thread.interrupted()) {   // 확인 + 리셋
            // 인터럽트됨 (이제 플래그 false)
            handleInterrupt();
        }
    }
    
    private void doWork() { }
    private void handleInterrupt() { }
}

3.7 자기 점검 답변

interrupt / isInterrupted / interrupted 차이는?

:
1. interrupt():

  • 대상 플래그 true
  • 인스턴스
  1. isInterrupted():

    • 대상 플래그 확인
    • 변경 X
  2. interrupted():

    • 현재 스레드 확인 + 리셋
    • static
  3. 핵심:

    • isInterrupted: 확인만
    • interrupted: 확인 + 리셋

4️⃣ interrupted()의 static과 리셋

4.1 static 인 이유

interrupted() 가 static 인 이유:

  현재 스레드의 플래그를 다룸.
  - Thread.currentThread() 대상
  - static (현재 스레드 묵시적)

  Thread.interrupted();
  ≡ 현재 스레드의 플래그

4.2 리셋하는 이유

리셋하는 이유:

  인터럽트 처리 후 플래그 초기화.
  - 한 번 처리하면 리셋
  - 같은 인터럽트 중복 처리 방지

  확인 + 리셋 = "인터럽트 소비"

4.3 동작

// interrupted() 동작
Thread.currentThread().interrupt();   // 플래그 true

boolean first = Thread.interrupted();   // true (확인 + 리셋)
boolean second = Thread.interrupted();  // false (이미 리셋)

// 첫 호출: true (그리고 리셋)
// 둘째 호출: false (리셋됨)

4.4 isInterrupted vs interrupted

// isInterrupted — 리셋 X
Thread.currentThread().interrupt();
boolean a = Thread.currentThread().isInterrupted();   // true
boolean b = Thread.currentThread().isInterrupted();   // true (그대로)

// interrupted — 리셋 O
Thread.currentThread().interrupt();
boolean c = Thread.interrupted();   // true (리셋)
boolean d = Thread.interrupted();   // false (리셋됨)

4.5 주의 — 의도치 않은 리셋

// ❌ 실수 — interrupted 로 플래그 소비
public void wrong() {
    if (Thread.interrupted()) {   // 확인 + 리셋
        // 처리
    }
    // 플래그 리셋됨
    // 이후 코드에서 인터럽트 모름
}

// ✓ 확인만 하려면 isInterrupted
public void correct() {
    if (Thread.currentThread().isInterrupted()) {   // 확인만
        // 처리
    }
    // 플래그 그대로
}

4.6 ILIC 의 맥락

public class InterruptedStaticExample {
    
    // interrupted — 인터럽트 소비 (처리)
    public void processWithInterruptCheck() {
        while (true) {
            if (Thread.interrupted()) {   // 확인 + 리셋
                log.info("Interrupt consumed, stopping");
                break;   // 처리 후 종료
            }
            doWork();
        }
    }
    
    // isInterrupted — 확인만 (소비 X)
    public void checkOnly() {
        while (!Thread.currentThread().isInterrupted()) {   // 확인만
            doWork();
        }
        // 플래그 유지 (cleanup 에서 다시 확인 가능)
    }
    
    private void doWork() { }
}

4.7 자기 점검 답변

interrupted()가 static이고 플래그를 리셋하는 이유는?

:
1. static:

  • 현재 스레드 대상
  • 묵시적
  1. 리셋:

    • 인터럽트 소비
    • 중복 처리 방지
  2. 동작:

    • 첫 호출 true (리셋)
    • 둘째 false
  3. 주의:

    • 의도치 않은 리셋
    • 확인만: isInterrupted

5️⃣ InterruptedException과 플래그

5.1 블로킹 메서드의 인터럽트

블로킹 메서드 + 인터럽트:

  wait(), sleep(), join() 등:
    - 인터럽트되면 InterruptedException
    - 플래그 false 로 리셋!

  → 예외 + 플래그 리셋

5.2 플래그 리셋

try {
    Thread.sleep(1000);   // 인터럽트되면
} catch (InterruptedException e) {
    // 여기 도달
    // ★ 플래그는 이미 false (리셋됨)
    
    boolean flag = Thread.currentThread().isInterrupted();   // false!
}

5.3 왜 리셋하나

예외 + 리셋 이유:

  - 예외로 인터럽트 알림
  - 플래그는 리셋 (예외가 처리)
  - 중복 방지

문제:
  - 예외 잡고 플래그 모름
  - 상위에서 인터럽트 못 알아챔
  - → 복원 필요 (다음 섹션)

5.4 InterruptedException 던지는 메서드

InterruptedException 던지는 메서드:

  - Thread.sleep()
  - Object.wait()
  - Thread.join()
  - BlockingQueue.put/take
  - Lock.lockInterruptibly()
  - Condition.await()
  - Future.get()

  모두 인터럽트 시 예외 + 플래그 리셋

5.5 시각화

InterruptedException 흐름:

스레드: sleep(1000)   (TIMED_WAITING)
        플래그 false

interrupt() → 플래그 true → sleep 깨어남
            → InterruptedException 던짐
            → 플래그 false (리셋!)

catch (InterruptedException e):
  플래그는 false (리셋됨)

5.6 ILIC 의 맥락

public class InterruptedExceptionExample {
    
    public void demonstrateReset() {
        Thread worker = new Thread(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // 인터럽트로 sleep 깨어남
                // ★ 플래그는 이미 false
                log.info("Interrupted, flag: {}", 
                    Thread.currentThread().isInterrupted());   // false!
                
                // 플래그 복원 필요 (다음 섹션)
                Thread.currentThread().interrupt();   // 복원
            }
        });
        worker.start();
        worker.interrupt();
    }
}

5.7 자기 점검 답변

InterruptedException 발생 시 플래그 상태는?

:
1. 리셋:

  • 예외 + 플래그 false
  • 이미 리셋됨
  1. 이유:

    • 예외가 인터럽트 알림
    • 중복 방지
  2. 던지는 메서드:

    • sleep, wait, join
    • BlockingQueue, Lock
  3. 문제:

    • catch 후 플래그 모름
    • 복원 필요

6️⃣ 플래그 복원

6.1 복원의 필요성

플래그 복원:

  InterruptedException catch 후
  플래그가 리셋됨.

  복원:
    Thread.currentThread().interrupt();

  이유:
    - 상위 코드가 인터럽트 알도록
    - 인터럽트 정보 유지

6.2 복원 패턴

// ✓ 플래그 복원
public void method() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();   // 복원
        // 상위가 인터럽트 알 수 있음
    }
}

6.3 복원 안 하면

// ❌ 복원 안 함 (인터럽트 정보 손실)
public void wrong() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // 아무것도 안 함 (플래그 리셋된 채)
    }
    // 상위 코드:
    while (!Thread.currentThread().isInterrupted()) {
        // 플래그 false → 인터럽트 무시
        // 영원히 루프
    }
}

6.4 복원 vs 전파

인터럽트 처리 방법:

1. 복원 (재설정)
   - Thread.currentThread().interrupt()
   - 상위가 처리

2. 전파 (예외 던지기)
   - throws InterruptedException
   - 호출자가 처리

3. 처리 (종료)
   - 직접 종료/정리

→ 절대 무시 X

6.5 권장 패턴

// 방법 1: 복원
public void restore() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();   // 복원
    }
}

// 방법 2: 전파 (가능하면)
public void propagate() throws InterruptedException {
    Thread.sleep(1000);   // 던짐 (호출자 처리)
}

// 방법 3: 종료
public void terminate() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        return;   // 종료
    }
}

6.6 ILIC 의 맥락

@Service
public class FlagRestoreExample {
    
    // ✓ 복원
    public void processWithRestore() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                Shipment shipment = queue.take();   // 인터럽트 가능
                process(shipment);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();   // 복원
                break;   // 루프 종료
            }
        }
        cleanup();
    }
    
    // ✓ 전파 (라이브러리 메서드)
    public Shipment takeWithPropagate() throws InterruptedException {
        return queue.take();   // 던짐 (호출자 처리)
    }
    
    private final BlockingQueue<Shipment> queue = new LinkedBlockingQueue<>();
    private void process(Shipment s) { }
    private void cleanup() { }
}

6.7 자기 점검 답변

인터럽트 플래그 복원의 필요성은?

:
1. 복원:

  • catch 후 플래그 리셋됨
  • interrupt() 로 복원
  1. 이유:

    • 상위가 인터럽트 알도록
    • 정보 유지
  2. 안 하면:

    • 인터럽트 무시
    • 영원히 루프
  3. 방법:

    • 복원 / 전파 / 종료
    • 절대 무시 X

7️⃣ 협력적 종료 패턴

7.1 협력적 종료

협력적 종료:

  스레드가 인터럽트를 확인하고
  스스로 안전하게 종료.

요소:
  - 플래그 확인
  - InterruptedException 처리
  - 자원 정리

7.2 기본 패턴

public void run() {
    try {
        while (!Thread.currentThread().isInterrupted()) {
            // 작업
            doWork();   // 인터럽트 가능
        }
    } catch (InterruptedException e) {
        // 블로킹 중 인터럽트
        Thread.currentThread().interrupt();
    } finally {
        // 안전한 정리
        cleanup();
    }
}

7.3 두 가지 확인 지점

인터럽트 확인 두 지점:

1. 플래그 확인 (반복 작업)
   - while (!isInterrupted())
   - CPU 작업 사이

2. InterruptedException (블로킹)
   - sleep, wait, take
   - 블로킹 중 인터럽트

→ 둘 다 처리

7.4 CPU 작업 + 블로킹

public void run() {
    try {
        while (!Thread.currentThread().isInterrupted()) {
            // CPU 작업 (플래그 확인)
            heavyComputation();
            
            // 블로킹 작업 (예외)
            Shipment s = queue.take();   // InterruptedException
            process(s);
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();   // 복원
    } finally {
        cleanup();
    }
}

7.5 graceful shutdown

// graceful shutdown
public class GracefulWorker {
    private Thread worker;
    
    public void start() {
        worker = new Thread(this::run);
        worker.start();
    }
    
    public void shutdown() throws InterruptedException {
        worker.interrupt();   // 중단 요청
        worker.join(5000);    // 최대 5초 대기
        if (worker.isAlive()) {
            log.warn("Worker did not stop in time");
        }
    }
    
    private void run() {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                processTask();
            }
        } finally {
            cleanup();   // 정리
        }
    }
    
    private void processTask() { }
    private void cleanup() { }
}

7.6 ILIC 의 맥락

@Service
public class CooperativeShutdown {
    
    private Thread processingWorker;
    private final BlockingQueue<Shipment> queue = new LinkedBlockingQueue<>();
    
    @PostConstruct
    public void start() {
        processingWorker = new Thread(this::processLoop, "shipment-worker");
        processingWorker.start();
    }
    
    private void processLoop() {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                Shipment shipment = queue.take();   // 블로킹 (인터럽트 가능)
                process(shipment);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();   // 복원
            log.info("Worker interrupted, shutting down");
        } finally {
            flushPending();   // 정리
        }
    }
    
    @PreDestroy
    public void shutdown() throws InterruptedException {
        processingWorker.interrupt();   // 중단 요청
        processingWorker.join(10000);   // 대기
    }
    
    private void process(Shipment s) { }
    private void flushPending() { }
}

7.7 자기 점검 답변

협력적 종료 패턴은?

:
1. 협력적:

  • 플래그 확인
  • 스스로 종료
  1. 두 지점:

    • 플래그 (반복)
    • 예외 (블로킹)
  2. 패턴:

    • while (!isInterrupted())
    • catch + 복원
    • finally cleanup
  3. graceful:

    • interrupt + join

8️⃣ 즉각 종료 패턴

8.1 while (!Thread.interrupted())

// 즉각 종료 패턴
while (!Thread.interrupted()) {   // 확인 + 리셋
    doWork();
}
// 인터럽트 시 즉시 종료

8.2 isInterrupted vs interrupted 루프

// 방법 1: isInterrupted (플래그 유지)
while (!Thread.currentThread().isInterrupted()) {
    doWork();
}
// 종료 후 플래그 true (cleanup 에서 확인 가능)

// 방법 2: interrupted (플래그 리셋)
while (!Thread.interrupted()) {
    doWork();
}
// 종료 후 플래그 false (소비됨)

8.3 선택

isInterrupted vs interrupted 루프:

isInterrupted (권장):
  - 플래그 유지
  - 이후 코드도 인터럽트 알 수 있음

interrupted:
  - 플래그 리셋
  - 인터럽트 소비
  - 이후 코드 모름

→ 보통 isInterrupted (유지)

8.4 빠른 종료

// 빠른 종료 — 여러 지점 확인
public void run() {
    while (!Thread.currentThread().isInterrupted()) {
        // 긴 작업 중간에도 확인
        for (int i = 0; i < 1000; i++) {
            if (Thread.currentThread().isInterrupted()) {
                return;   // 빠른 종료
            }
            processItem(i);
        }
    }
}

8.5 블로킹 + 즉각 종료

// 블로킹 작업 + 즉각 종료
public void run() {
    try {
        while (!Thread.currentThread().isInterrupted()) {
            Shipment s = queue.take();   // 인터럽트 시 즉시 예외
            process(s);
        }
    } catch (InterruptedException e) {
        // 즉시 종료 (예외로 빠짐)
        Thread.currentThread().interrupt();
    }
}
// take 가 인터럽트 시 즉시 예외 → 빠른 종료

8.6 ILIC 의 맥락

@Service
public class ImmediateShutdown {
    
    private final BlockingQueue<Shipment> queue = new LinkedBlockingQueue<>();
    
    // 즉각 종료 패턴
    public void run() {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                // 블로킹 — 인터럽트 시 즉시 예외
                Shipment shipment = queue.take();
                
                // 긴 처리 중에도 확인
                processWithChecks(shipment);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.info("Immediate shutdown");
        }
    }
    
    private void processWithChecks(Shipment shipment) throws InterruptedException {
        // 단계별 인터럽트 확인 (빠른 종료)
        if (Thread.currentThread().isInterrupted()) {
            throw new InterruptedException();
        }
        validateShipment(shipment);
        
        if (Thread.currentThread().isInterrupted()) {
            throw new InterruptedException();
        }
        calculateFreight(shipment);
    }
    
    private void validateShipment(Shipment s) { }
    private void calculateFreight(Shipment s) { }
}

8.7 자기 점검 답변

즉각 종료 패턴은?

:
1. 패턴:

  • while (!Thread.interrupted())
  • 또는 isInterrupted
  1. 선택:

    • isInterrupted: 유지 (권장)
    • interrupted: 리셋 (소비)
  2. 빠른 종료:

    • 여러 지점 확인
    • 블로킹 + 예외
  3. 즉시:

    • take 인터럽트 시 예외

9️⃣ 면접 + 자기 점검

9.1 면접 단골 질문 매핑

Q핵심 답변
인터럽트?중단 요청 (협력적)
강제 종료?아니다 (플래그)
interrupt()?플래그 설정
isInterrupted()?확인 (변경 X)
interrupted()?확인 + 리셋 (static)
InterruptedException 플래그?리셋됨
복원?interrupt() 재호출
협력적 종료?플래그 확인 + 정리
즉각 종료?while (!interrupted())
인터럽트 무시?위험 (안 멈춤)

9.2 자기 점검 체크리스트

인터럽트

  • 정의
  • 협력적
  • 플래그

강제 X

  • stop 위험
  • 무시 가능

세 메서드

  • interrupt
  • isInterrupted
  • interrupted

interrupted

  • static
  • 리셋

InterruptedException

  • 플래그 리셋
  • 던지는 메서드

복원

  • 필요성
  • 방법

종료 패턴

  • 협력적
  • 즉각

9.3 추가 심화 질문

Q1: 인터럽트 무시하면?

답:

  • 종료 신호 사라짐
  • 스레드 안 멈춤
  • graceful shutdown 실패
  • 최소한 복원 또는 종료

Q2: 인터럽트와 BLOCKED?

답:

  • synchronized BLOCKED: 인터럽트 X (안 깸)
  • wait/sleep WAITING: InterruptedException
  • lockInterruptibly: 인터럽트 O
  • BLOCKED 만 인터럽트 무시

Q3: 인터럽트와 IO?

답:

  • 전통 IO (InputStream): 인터럽트 X
  • NIO (InterruptibleChannel): 인터럽트 O
  • 소켓 close 로 우회
  • IO 마다 다름

Q4: 인터럽트 정책?

답:

  • 라이브러리: 전파 (throws)
  • 애플리케이션: 복원 또는 종료
  • 절대 삼키지 X
  • 일관된 정책

Q5: ExecutorService 와 인터럽트?

답:

  • shutdownNow(): 인터럽트 발생
  • 작업이 인터럽트 처리해야
  • shutdown(): 인터럽트 X (완료 대기)
  • 협력 필요

🎯 핵심 요약 — 3줄 정리

1. 인터럽트

  • 중단 요청 (협력적, 강제 X)
  • 플래그 설정

2. 세 메서드

  • interrupt: 설정, isInterrupted: 확인
  • interrupted: 확인 + 리셋 (static)

3. 예외와 복원

  • InterruptedException: 플래그 리셋
  • 복원: Thread.currentThread().interrupt()
  • 절대 무시 X (협력적 종료)

📚 다음으로...

Unit 6.4 — yield() (Phase 6 마지막)

이번 Unit에서 인터럽트를 봤다면, 다음은 yield() (Phase 6 마지막).

  • yield() 의 동작 (양보 힌트)
  • RUNNABLE 유지
  • sleep/wait 와 상태 비교
  • Phase 6 완주 + 졸업 시험

Phase 6 진행 상황

🚀 Phase 6 — 스레드 간 협력
  ✅ Unit 6.1 생산자-소비자 문제
  ✅ Unit 6.2 wait()과 notify()
  ✅ Unit 6.3 인터럽트 메커니즘 ← 여기
  ⏭ Unit 6.4 yield() — Phase 6 완주

4주차 누적 진행

✅ Phase 1~5 (21 Unit, 1차 정점 완료)
🚀 Phase 6 — 스레드 협력 (3/4 진행)

총: 24/35 Unit
profile
Software Developer

0개의 댓글