JavaのThreadクラスinterruptメソッドを徹底解説!初心者でもわかるスレッドの中断方法
生徒
「Javaでスレッドを止めたいときってどうすればいいんですか?強制的に止める方法があるんですか?」
先生
「完全に強制終了する方法は推奨されていませんが、interruptメソッドを使うとスレッドに『中断してね』という指示を出すことができます。」
生徒
「なるほど!でも、それって本当にスレッドが止まるんですか?」
先生
「実際には『お願いベース』なんです。スレッドが中断のサインを受け取って、自分で処理を止める仕組みなんですよ。」
1. java.langパッケージとThreadクラス
「1. java.langパッケージとThreadクラス」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。
Javaのjava.langパッケージには、プログラムを作る上で最も基本的で重要なクラスが含まれています。その中のThreadクラスは、マルチスレッド処理を行うための中核的な存在です。スレッドを利用することで、同時に複数の処理を走らせることができ、効率的で応答性の高いプログラムを作成できます。
2. interruptメソッドとは?
interruptメソッドは、スレッドに対して「中断してほしい」というリクエストを送るためのメソッドです。実際にスレッドを強制終了するのではなく、対象のスレッドに「割り込みフラグ」を立てるだけです。
このフラグは、スレッドがsleepやwaitなどの待機状態にあるときには例外を発生させ、それ以外の場合にはスレッドが自分でチェックして処理を終了するきっかけを作ります。
3. interruptの基本的な使い方
以下に、スレッドを中断するための基本的なコード例を示します。
public class InterruptExample extends Thread {
public void run() {
try {
for (int i = 0; i < 5; i++) {
System.out.println("スレッド実行中: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("スレッドが中断されました");
}
}
public static void main(String[] args) {
InterruptExample thread = new InterruptExample();
thread.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}
スレッド実行中: 0
スレッド実行中: 1
スレッドが中断されました
この例では、スレッドがsleep中にinterruptが呼ばれることでInterruptedExceptionが発生し、スレッドは処理を中断します。
4. interruptが有効に働く場面
「4. interruptが有効に働く場面」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。
interruptメソッドが有効に機能する場面は主に以下の二つです。
sleep、wait、joinなどのブロッキングメソッド中に呼び出された場合- スレッド内で定期的に
isInterruptedやThread.interrupted()を確認している場合
つまり、スレッドがきちんと「割り込み」に対応するコードを書いていなければ、interruptを呼んでも効果がないということです。
5. isInterruptedとの組み合わせ
スレッド内で割り込みフラグを確認するために使うのがisInterruptedメソッドです。これを使えば、スレッドが自ら「割り込まれたかどうか」を判定して安全に終了処理を行うことができます。
public class InterruptCheckExample extends Thread {
public void run() {
while (!isInterrupted()) {
System.out.println("処理を継続中...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("割り込み例外をキャッチしました");
interrupt(); // フラグを再度設定
}
}
System.out.println("スレッドを終了します");
}
public static void main(String[] args) {
InterruptCheckExample thread = new InterruptCheckExample();
thread.start();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}
処理を継続中...
処理を継続中...
割り込み例外をキャッチしました
スレッドを終了します
このように、isInterruptedを利用することで、スレッドが安全に終了できる仕組みを実装できます。
6. interruptとstopの違い
Javaにはかつてstopメソッドも存在しましたが、現在は非推奨です。stopはスレッドを強制終了させるため安全性が低く、データ不整合や予期しない動作の原因となるため避けるべきです。
一方でinterruptは、スレッドに終了を促す「合図」を送る仕組みなので、安全で柔軟なスレッド制御が可能です。
7. 実務での活用ポイント
「7. 実務での活用ポイント」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。
実際の開発現場では、interruptは長時間動作する処理やキャンセル機能を持つアプリケーションで多用されます。例えば、大量のデータを処理するバッチ処理、ファイル入出力、ネットワーク通信のキャンセルなどで役立ちます。
初心者のうちに「スレッドは必ず安全に止める」という習慣をつけると、後で大規模なプログラムを書いたときに大きな助けになります。
まとめ
Threadクラスのinterruptメソッドを振り返ろう
JavaのThreadクラスに用意されているinterruptメソッドは、スレッドを安全に中断したいときに使う重要なメソッドです。マルチスレッド処理では、複数の処理が同時に動くため、長時間続く処理や待機中の処理を途中で止めたい場面があります。そのようなときに、いきなり強制終了するのではなく、スレッドに中断の合図を送る仕組みとしてinterruptメソッドを使います。
初心者が注意したいのは、interruptメソッドはスレッドを強制的に止める命令ではないという点です。interruptは、対象のスレッドに対して中断してほしいという合図を送るメソッドです。スレッドがその合図を受け取り、自分で終了処理を行うことで、安全に処理を終えることができます。この考え方を理解しておくと、Javaのスレッド制御やマルチスレッドプログラミングの理解が深まります。
Javaでは、昔から存在するstopメソッドを使うとスレッドを強制終了できるように見えます。しかし、stopは安全性の問題があるため現在は推奨されません。強制的に処理を止めると、データの更新途中で終了してしまったり、ファイルやネットワーク接続の後片付けができなかったりする可能性があります。そのため、実務ではinterruptを使って、スレッド自身に安全な終了を任せる考え方が大切になります。
interruptは割り込みフラグを立てる仕組み
interruptメソッドを呼び出すと、対象のスレッドには割り込みフラグが設定されます。この割り込みフラグは、スレッドが中断要求を受け取ったことを示す目印のようなものです。スレッドが通常の計算処理をしている場合は、interruptを呼び出しただけで自動的に処理が止まるわけではありません。スレッド内でisInterruptedメソッドなどを使って割り込み状態を確認し、自分で終了する処理を書く必要があります。
一方で、Thread.sleep、wait、joinなどの待機処理を実行しているスレッドにinterruptが送られると、InterruptedExceptionが発生します。これは、待機している処理に対して中断要求が届いたことを知らせるための例外です。この例外をcatchで受け取り、終了メッセージを表示したり、必要な後片付けを行ったりすることで、スレッドを安全に止めることができます。
つまり、interruptを正しく使うには、割り込みフラグの確認とInterruptedExceptionへの対応が欠かせません。単にthread.interruptと書くだけではなく、スレッド側が中断に対応するコードになっているかを確認することが大切です。
isInterruptedと組み合わせて安全に終了する
長時間動作するスレッドでは、while文などで処理を繰り返すことがあります。このような処理では、定期的にisInterruptedメソッドを確認することで、中断要求が来たらループを抜けるようにできます。これにより、スレッドは自分のタイミングで安全に終了できます。
public class InterruptSummaryExample extends Thread {
public void run() {
while (!isInterrupted()) {
try {
System.out.println("処理を実行中です");
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("中断要求を受け取りました");
interrupt();
}
}
System.out.println("安全にスレッドを終了します");
}
public static void main(String[] args) {
InterruptSummaryExample thread = new InterruptSummaryExample();
thread.start();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}
処理を実行中です
処理を実行中です
処理を実行中です
中断要求を受け取りました
安全にスレッドを終了します
このサンプルでは、スレッドが繰り返し処理を行いながら、interruptによる中断要求を受け取ると安全に終了します。sleep中に割り込みが発生した場合はInterruptedExceptionが発生するため、catchの中でinterruptを再度呼び出して割り込みフラグを戻しています。この書き方を理解しておくと、実務でも安全なスレッド終了処理を考えやすくなります。
実務でinterruptが役立つ場面
Javaの実務開発では、interruptメソッドは長時間動作する処理やキャンセル可能な処理で役立ちます。たとえば、大量データを処理するバッチ処理、時間のかかるファイル読み込み、外部サーバーとのネットワーク通信、検索処理のキャンセル、バックグラウンド処理の停止などです。利用者が処理をキャンセルしたときや、システム終了時にスレッドを安全に止めたいときにinterruptの考え方が重要になります。
もし強制的にスレッドを止めてしまうと、処理中のデータが途中までしか更新されなかったり、ロックが解放されなかったり、ファイルが閉じられなかったりする可能性があります。これらは業務システムでは重大な不具合につながります。interruptを使えば、スレッドに終了の合図を送り、スレッド側で必要な後片付けをしてから終了できます。
特にマルチスレッド処理では、スレッドの開始方法だけでなく、終了方法を設計することが非常に重要です。処理を始めることは比較的簡単ですが、安全に終わらせることは意識しないと難しくなります。Java初心者のうちから、スレッドは無理やり止めるのではなく、interruptで合図を送り、スレッド自身に終了させるという考え方を身につけておきましょう。
初心者がつまずきやすい注意点
interruptメソッドでよくある誤解は、呼び出した瞬間にスレッドが必ず止まると思ってしまうことです。実際には、スレッドが割り込みに対応していなければ、interruptを呼び出しても処理が続くことがあります。たとえば、長いwhile文の中でisInterruptedを確認していない場合、スレッドは中断要求に気づかず処理を続けてしまいます。
また、InterruptedExceptionをcatchしたときに何もしないまま処理を続けるのも避けたい書き方です。例外を受け取ったということは、中断要求が届いたという意味を持ちます。そのため、ログを出す、ループを抜ける、後片付けをする、必要に応じてinterruptを再度呼び出すなど、目的に合った対応が必要です。
この記事では、java.langパッケージ、Threadクラス、interruptメソッド、割り込みフラグ、InterruptedException、isInterrupted、sleep、wait、join、stopメソッドとの違い、実務でのキャンセル処理について学びました。これらはJavaのマルチスレッド処理を安全に扱うための重要な知識です。
Javaのスレッド制御では、処理を早く動かすことだけでなく、必要なときに安全に止めることも大切です。interruptはそのための基本的な仕組みであり、スレッドに中断をお願いする合図として使います。中断要求を受け取ったスレッドが、自分で状態を確認し、必要な処理を終えて終了することで、安定したプログラムを作ることができます。
生徒
「interruptメソッドは、スレッドを強制的に止めるメソッドではないんですね。」
先生
「その通りです。スレッドに中断してほしいという合図を送るメソッドです。」
生徒
「だから、スレッド側で中断に対応するコードが必要なんですね。」
先生
「はい。isInterruptedを確認したり、InterruptedExceptionを正しく処理したりすることが大切です。」
生徒
「sleep中にinterruptされると例外が発生することも分かりました。」
先生
「そうです。sleep、wait、joinのような待機処理ではInterruptedExceptionが重要になります。」
生徒
「stopメソッドで強制終了するより、interruptで安全に止めるほうが良いんですね。」
先生
「その考え方が大切です。強制終了はデータ不整合の原因になるため、現在は推奨されません。」
生徒
「実務でもバッチ処理やファイル処理のキャンセルで使えそうです。」
先生
「はい。長時間動作する処理やバックグラウンド処理を安全に終了させるときに役立ちます。」
生徒
「スレッドは開始するだけでなく、終了方法まで考えることが大事なんですね。」
先生
「よく理解できています。interruptの考え方を覚えておくと、安全なマルチスレッド処理に一歩近づけます。」