스레드에서 인터럽트(interrupt)는 스레드에게 특정한 작업을 중단하거나 변경할 필요가 있음을 알리는 신호입니다. 자바에서는 interrupt() 메서드를 사용해 스레드에 인터럽트 신호를 보낼 수 있습니다. 스레드가 인터럽트 상태가 되면, 이 상태를 확인하고 처리해야 합니다. 자바에서는 인터럽트 상태를 관리하기 위해 몇 가지 메서드가 제공됩니다: isInterrupted()와 interrupted()가 그 예입니다.
스레드에 인터럽트 신호가 보내지면, 해당 스레드는 인터럽트 상태가 true로 설정됩니다. 이 상태는 스레드가 특정 동작을 변경하거나 작업을 중단해야 할 때 유용합니다.
그러나 인터럽트 상태가 한 번 true로 설정되면, 이 상태를 적절하게 처리해야 합니다. 그렇지 않으면, 스레드가 계속해서 인터럽트 상태에 놓이게 되어 이후 작업이 중단되거나 비정상적인 동작을 초래할 수 있습니다.
자바에서 스레드의 인터럽트 상태를 확인하거나 인터럽트 상태를 리셋하기 위해 두 가지 메서드가 제공됩니다: isInterrupted()와 interrupted().
1) isInterrupted()
예시:
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
// 작업 수행
}
});
위 코드에서 isInterrupted()는 스레드가 인터럽트 상태인지를 확인하고, true이면 루프를 중단하게 합니다. 이때, 인터럽트 상태는 그대로 유지됩니다.
2) interrupted()
예시:
Thread thread = new Thread(() -> {
while (!Thread.interrupted()) { // 상태 확인 후 리셋됨
// 작업 수행
}
});
위 코드에서 interrupted()는 스레드가 인터럽트 상태인지 확인한 후, 인터럽트 상태를 false로 리셋합니다. 이 메서드를 반복해서 호출하면 첫 번째 호출 후에는 항상 false가 반환됩니다.
인터럽트가 발생했을 때, 인터럽트 상태를 확인한 후 다시 false로 리셋하지 않으면, 스레드가 계속해서 인터럽트 상태로 유지되게 됩니다. 이것은 의도하지 않은 작업 중단이나 예외 발생을 초래할 수 있습니다.
예시: 인터럽트 상태를 리셋하지 않는 경우
Thread thread = new Thread(() -> {
try {
Thread.sleep(10000); // 10초 동안 잠자기
} catch (InterruptedException e) {
// InterruptedException 발생 시 인터럽트 상태가 자동으로 리셋됨
System.out.println("인터럽트 발생");
}
});
thread.start();
thread.interrupt(); // 스레드에 인터럽트 신호
따라서, 인터럽트 상태를 다시 false로 돌리는 이유는 스레드가 의도하지 않게 이후에도 계속 인터럽트 상태를 유지하지 않도록 하기 위해서입니다. 인터럽트 상태가 계속 true로 유지되면, 스레드가 이후 실행 중인 다른 작업에서도 계속 방해를 받을 수 있습니다.
InterruptedException은 스레드가 대기, 슬립, 조인 등의 작업을 수행하는 중에 인터럽트가 발생하면 던져지는 예외입니다. 이 예외가 발생하면, 인터럽트 상태가 자동으로 false로 리셋됩니다. 이 때문에, InterruptedException이 발생한 후에는 다시 인터럽트 상태를 설정해 주어야 할 때도 있습니다.
예시:
Thread thread = new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// 인터럽트가 발생하면 예외 처리 후 상태 리셋
Thread.currentThread().interrupt(); // 상태를 다시 true로 설정
}
});
위 코드에서는 InterruptedException 발생 후 상태가 리셋되지만, 다시 interrupt()를 호출하여 상태를 true로 재설정하고 있습니다. 이를 통해 이후에 스레드가 적절하게 인터럽트 상태를 반영할 수 있게 됩니다.
인터럽트 상태를 확인한 후 상태를 리셋하지 않으면, 스레드는 계속해서 인터럽트 상태로 남아 있게 됩니다. 이로 인해 스레드가 수행하는 작업이 지속적으로 방해될 수 있습니다.
구체적인 문제:
스레드가 재작업을 계속 방해받을 수 있음: 인터럽트 상태가 유지된 채로 스레드가 실행되면, 이후에 실행되는 다른 메서드나 작업들도 인터럽트 상태를 인식하고 중단되거나 방해받을 수 있습니다. 예를 들어, 스레드가 반복적으로 대기, 슬립, 조인과 같은 작업을 수행할 때마다 InterruptedException이 발생할 수 있습니다.
정상적인 실행 흐름 방해: 인터럽트 상태가 리셋되지 않으면, 스레드는 다른 코드에서 예상치 못한 동작을 할 수 있습니다. 특히 대기 상태에서 깨어나는 동작이 여러 번 일어날 수 있습니다.
따라서 인터럽트가 한 번 처리되면, 그 상태를 적절히 리셋하여 스레드가 다시 정상적인 상태로 돌아가게 해야 합니다.
InterruptedException은 스레드가 대기, 슬립, 조인과 같은 작업 중에 인터럽트가 발생하면 던져지는 예외입니다. 이 예외가 발생하면, 자바는 스레드의 인터럽트 상태를 자동으로 false로 리셋합니다. 그 이유는 인터럽트 신호를 한 번 처리한 후 스레드가 더 이상 중단되지 않고, 다시 정상 상태로 돌아가도록 보장하기 위해서입니다.
자동 리셋의 이유:
예시:
try {
Thread.sleep(10000); // 스레드가 슬립 상태로 진입
} catch (InterruptedException e) {
// InterruptedException이 발생하면 인터럽트 상태가 자동으로 false로 리셋됨
System.out.println("인터럽트 발생");
}
여기서 Thread.sleep() 메서드가 인터럽트되면, InterruptedException이 발생하고 인터럽트 상태는 자동으로 리셋됩니다. 이렇게 하여 스레드는 인터럽트 신호를 한 번 처리한 후 정상적인 흐름을 계속 유지할 수 있습니다.
isInterrupted()와 interrupted()는 각각의 용도에 맞게 사용하는 것이 중요합니다. 각 메서드는 스레드의 인터럽트 상태를 확인하거나 상태를 리셋하는 데 사용됩니다.
1) isInterrupted()의 적절한 사용
사용 예:
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
// 스레드가 인터럽트되지 않았을 때 계속 실행
}
});
이 예시에서 isInterrupted()는 현재 스레드의 상태를 확인하기만 할 뿐, 상태를 리셋하지 않습니다. 스레드가 인터럽트 상태를 유지하면서 특정 작업을 계속 수행할 수 있습니다.
2) interrupted()의 적절한 사용
사용 예:
Thread thread = new Thread(() -> {
while (!Thread.interrupted()) { // 상태를 확인하고 동시에 리셋
// 스레드가 인터럽트되지 않았을 때 계속 실행
}
});
이 코드에서 interrupted()는 인터럽트 상태를 확인한 후 자동으로 상태를 false로 리셋하여, 한 번 인터럽트 신호를 처리한 후 스레드가 다시 정상적으로 작업을 이어갈 수 있게 합니다.
요약: