1. 序章

この短い記事では、 Javaでのスレッドの停止について説明します。これは、Thread.stop()メソッドが非推奨になっているため、それほど単純ではありません。

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 を使用しており、に設定することで実行を開始/停止できます。真/偽。

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

3. スレッドを中断する

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

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

これらの状況で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);
        stopped.set(false);
        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
        }
        stopped.set(true);
    }
}

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

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

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

4. 結論

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

いつものように、完全なソースコードはGitHubから入手できます。