Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaで実行中のスレッドを中断(割り込み)する方法をわかりやすく解説

スレッドへの割り込み(interrupt)とは

Javaであるスレッドを中断したい場合、対象となるThreadオブジェクトに対してinterrupt()メソッドを呼び出します。つまり、スレッドの割り込みは、別のスレッドからinterrupt()メソッドが呼び出されることによって発生します。

なお、interrupt()はスレッドを強制的に停止させるものではなく、「割り込み要求が出された」というフラグを立てるだけです。実際に処理を中断するかどうかは、ターゲット側のスレッドがフラグを確認して自ら終了処理を行う、いわゆる「協調的なキャンセル」によって実現されます。

Threadクラスが提供する3つの割り込み関連メソッド

  • void interrupt() … 対象のスレッドに割り込みをかけます(割り込みフラグをセットします)。
  • static boolean interrupted() … 現在実行中のスレッドが割り込まれたかどうかを判定し、同時に割り込みステータスをクリア(リセット)します。
  • boolean isInterrupted() … 対象のスレッドが割り込まれたかどうかを判定します。こちらはステータスをクリアしません。

interrupted() と isInterrupted() の違い

どちらも割り込み状態を確認するメソッドですが、interrupted()は静的メソッドであり、呼び出すとJVMによって割り込みフラグがfalseにリセットされる点が特徴です。一方、isInterrupted()はインスタンスメソッドで、フラグを変更せずに状態を参照できます。用途に応じて使い分けることが重要です。

サンプルコード

public class ThreadInterruptTest {
    public static void main(String[] args) {
        System.out.println("Thread main started");
        final Task task = new Task();
        final Thread thread = new Thread(task);
        thread.start();
        thread.interrupt(); // interrupt() メソッドを呼び出し
        System.out.println("Main Thread finished");
    }
}
class Task implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("[" + Thread.currentThread().getName() + "] Message " + i);
            if(Thread.interrupted()) {
                System.out.println("This thread was interruped by someone calling this Thread.interrupt()");
                System.out.println("Cancelling task running in thread " + Thread.currentThread().getName());
                System.out.println("After Thread.interrupted() call, JVM reset the interrupted value to: " + Thread.interrupted());
                break;
            }
        }
    }
}

実行結果

Thread main started
Main Thread finished
[Thread-0] Message 0
This thread was interruped by someone calling this Thread.interrupt()
Cancelling task running in thread Thread-0
After Thread.interrupted() call, JVM reset the interrupted value to: false

コードのポイント解説

この例では、mainスレッドがTaskを実行する新しいスレッドを開始した直後にinterrupt()を呼び出しています。タスク側では、ループの中でThread.interrupted()を使って割り込みを検知すると、メッセージを出力してタスクをキャンセルし、breakでループを抜けています。

また、実行結果からは、Thread.interrupted()を一度呼び出した後、割り込みフラグがJVMによってfalseにリセットされていることも確認できます。これは前述の通り、interrupted()がステータスを消費(クリア)するメソッドだからです。

なお、スレッドがsleep()wait()などでブロックされている状態で割り込みを受けると、InterruptedExceptionがスローされる点にも注意してください。ブロック中のスレッドを中断する場合は、例外を適切にcatchして終了処理を行うのが一般的なパターンです。

  1. JavaでArrayListを初期化する方法|Arrays.asList()の使い方を解説

    Javaでリストを初期化する際には、Arrays.asList()メソッドとArrayListクラスが活用されます。通常のListインターフェースは直接オブジェクトを生成できないため、空のリストを作成するにはArrayListクラスが必要です。さらに、Arrays.asList()メソッドを使えば、初期値を持つArrayListを簡単に初期化できます。 ArrayListとは?Javaにおける基本的な役割 ArrayListの初期化とは、あらかじめ用意した値のセットをリストに代入する処理のことです。JavaでArrayListを扱うには、その初期化方法を理解しておくことが不可欠です。 ここで

  2. Androidで現在のスレッドが中断されているかどうかを確認する方法

    具体例に入る前に、まずスレッドについて簡単におさらいしておきましょう。スレッドとは軽量なサブプロセスであり、UIの動作を妨げることなくバックグラウンド処理を実行するために使われます。本記事では、Androidアプリにおいて現在実行中のスレッドが中断(interrupt)されているかどうかを確認する方法を、実際のサンプルコードとともに解説します。ポイントは Thread.currentThread().isInterrupted() メソッドです。このメソッドは、対象スレッドに割り込みが発生していれば true を、そうでなければ false を返します。手順1:新規プロジェクトの作成Andro