Javaスレッドを強制終了する方法

Javaスレッドを強制終了する方法

1. 前書き

この短い記事では、we’ll cover stopping a Thread in Java – which is not that simple since the Thread.stop() method is deprecated.

this update from Oracle,で説明されているように、stop()は、監視対象オブジェクトの破損につながる可能性があります。

2. フラグの使用

スレッドを作成して開始するクラスから始めましょう。 このタスクはそれ自体では終了しないため、そのスレッドを停止する何らかの方法が必要です。

そのためにアトミックフラグを使用します。

public class ControlSubThread implements Runnable {

    private Thread worker;
    private final AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    public ControlSubThread(int sleepInterval) {
        interval = sleepInterval;
    }

    public void start() {
        worker = new Thread(this);
        worker.start();
    }

    public void stop() {
        running.set(false);
    }

    public void run() {
        running.set(true);
        while (running.get()) {
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                System.out.println(
                  "Thread was interrupted, Failed to complete operation");
            }
            // do something here
         }
    }
}

定数trueを評価するwhileループを作成するのではなく、AtomicBooleanを使用しており、true/false.に設定することで実行を開始/停止できます。

introduction to Atomic Variablesで説明したように、AtomicBooleanを使用すると、異なるスレッドからの変数の設定とチェックでの競合を防ぐことができます。

3. Threadの割り込み

sleep()が長い間隔に設定されている場合、または解放されない可能性のあるlockを待機している場合はどうなりますか?

長期間ブロックしたり、正常に終了しなかったりするリスクに直面しています。

これらの状況でinterrupt()を作成できます。いくつかのメソッドと、新しいフラグをクラスに追加しましょう。

public class ControlSubThread implements Runnable {

    private Thread worker;
    private AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    // ...

    public void interrupt() {
        running.set(false);
        worker.interrupt();
    }

    boolean isRunning() {
        return running.get();
    }

    boolean isStopped() {
        return stopped.get();
    }

    public void run() {
        running.set(true);
        while (running.get()) {
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                System.out.println(
                  "Thread was interrupted, Failed to complete operation");
            }
            // do something
        }
    }
}

runningフラグをfalseに設定し、ワーカースレッドのinterrupt()メソッドを呼び出すinterrupt()メソッドを追加しました。

これが呼び出されたときにスレッドがスリープしている場合、他のブロッキング呼び出しと同様に、sleep()InterruptedException,で終了します。

これによりスレッドがループに戻り、runningがfalseであるため終了します。

4. 結論

このクイックチュートリアルでは、アトミック変数を使用する方法を確認しました。オプションで、interrupt(),の呼び出しと組み合わせて、スレッドをクリーンにシャットダウンします。 これは、非推奨のstop()メソッドを呼び出して、永久にロックしてメモリが破損するリスクを冒すよりも、間違いなく望ましい方法です。

いつものように、完全なソースコードはover on GitHubで利用できます。