JavaのInterruptedExceptionを完全ガイド!初心者でも理解できるスレッド制御と例外処理
生徒
「Javaでスレッドを使っていたら、InterruptedExceptionというエラーが出たんですが、これは何ですか?」
先生
「InterruptedExceptionは、スレッドがsleepやwait、joinなどで待機中に割り込まれたときに発生するチェック例外です。スレッドプログラミングをすると必ず出会う重要な例外ですよ。」
生徒
「なるほど。普通にプログラムを書いているだけでは出ないんですね。どんなときに使われるんですか?」
先生
「マルチスレッドの処理で待機や同期を行うときによく使われます。具体例を交えて見ていきましょう。」
1. InterruptedExceptionとは?
JavaのInterruptedExceptionは、java.langパッケージに含まれるチェック例外で、スレッドが待機やスリープ中に割り込みが発生したときにスローされます。スレッドを安全に停止したり、他の処理を優先させたいときに活用される仕組みです。初心者にとっては聞き慣れないかもしれませんが、マルチスレッド処理を正しく扱うためには必須の知識です。
2. sleepメソッドとInterruptedException
Thread.sleep()メソッドは指定時間スレッドを休止させます。しかし、この間に別のスレッドから割り込みが入るとInterruptedExceptionが発生します。
public class SleepExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
System.out.println("スレッドを3秒休止します");
Thread.sleep(3000);
System.out.println("休止終了");
} catch (InterruptedException e) {
System.out.println("スレッドが割り込まれました");
}
});
thread.start();
thread.interrupt(); // 割り込みを送る
}
}
スレッドを3秒休止します
スレッドが割り込まれました
このように、休止中のスレッドに割り込みを送ると待機が中断され、例外が発生します。
3. waitとnotifyでのInterruptedException
Object.wait()を使った同期処理でもInterruptedExceptionは発生します。スレッドが待機している間に割り込まれると、処理が強制的に終了します。
public class WaitExample {
public static void main(String[] args) {
Object lock = new Object();
Thread t = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("待機開始");
lock.wait();
System.out.println("待機解除");
} catch (InterruptedException e) {
System.out.println("待機中に割り込まれました");
}
}
});
t.start();
t.interrupt(); // 割り込み
}
}
待機開始
待機中に割り込まれました
このように、待機メソッドを使った場合も割り込み処理を考慮する必要があります。
4. joinメソッドとInterruptedException
Thread.join()は、他のスレッドが終了するまで待機するメソッドです。この待機も途中で割り込まれるとInterruptedExceptionになります。
public class JoinExample {
public static void main(String[] args) {
Thread worker = new Thread(() -> {
try {
Thread.sleep(2000);
System.out.println("ワーカースレッド終了");
} catch (InterruptedException e) {
System.out.println("ワーカーが中断されました");
}
});
worker.start();
try {
worker.join(); // ワーカーが終わるまで待機
System.out.println("メインスレッド続行");
} catch (InterruptedException e) {
System.out.println("待機中に割り込まれました");
}
}
}
このように、スレッド間の待機処理には必ず割り込みを考慮する必要があります。
5. InterruptedExceptionを回避・処理する方法
InterruptedExceptionは避けることができない性質の例外です。そのため、正しく処理する方法を理解することが大切です。よく使われるパターンとしては以下の通りです。
- 例外をキャッチして処理を終了する
- 例外をキャッチして割り込みフラグを再設定する
- 安全にリソースを解放してから終了する
public class HandleExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
while (true) {
System.out.println("処理中...");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("安全に終了します");
Thread.currentThread().interrupt(); // 割り込み状態を再設定
}
});
thread.start();
thread.interrupt();
}
}
処理中...
安全に終了します
このように、処理を中断しつつリソースを解放できるようにするのが基本です。
6. 初心者が注意すべきポイント
初心者がマルチスレッドを学ぶとき、InterruptedExceptionを軽視してしまうことがよくあります。しかし、Javaのスレッド制御では非常に重要な例外であり、適切に処理しないとプログラムが不安定になったりリソースが解放されない問題につながります。
特に以下のポイントを覚えておきましょう。
sleepやwait、joinなどのメソッドでは必ず発生しうる- 割り込みは「例外」ではなく「他のスレッドからの合図」だと理解する
- 処理の中断やリソース解放のタイミングを適切に設計する
こうした意識を持つことで、スレッドプログラミングを安全に進めることができます。