Javaマルチスレッド研究ノート-スレッドを完全に中断する方法

1.スレッドを中断します

        run()メソッドが完了すると、スレッドは自動的に破棄されます。ただし、スレッドがライフサイクルを完了する前に、スレッドを強制終了/停止する必要がある場合があります。以前は、メソッドsuspend()resume()、およびstop()を使用してスレッドの実行を管理していました。ただし、これらのメソッドはシステムをクラッシュさせる可能性があるため、Javaでは非推奨になっています。

        スレッドを一時停止/停止する方法は、ブールフラグとThread.interrupt()メソッドを使用することです。

1.ブールフラグを使用する

        クラス内のブールフラグとstopメソッドを使用して、Runnableインターフェイスを実装するクラスを作成します。

class MyThread implements Runnable {
 
    // to stop the thread
    private boolean exit;
 
    private String name;
    Thread t;
 
    MyThread(String threadname)
    {
        name = threadname;
        t = new Thread(this, name);
        System.out.println("New thread: " + t);
        exit = false;
        t.start(); // Starting the thread
    }
 
    // execution of thread starts from run() method
    public void run()
    {
        int i = 0;
        while (!exit) {
            System.out.println(name + ": " + i);
            i++;
            try {
                Thread.sleep(100);
            }
            catch (InterruptedException e) {
                System.out.println("Caught:" + e);
            }
        }
        System.out.println(name + " Stopped.");
    }
 
    // for stopping the thread
    public void stop()
    {
        exit = true;
    }
}
 
// Main class
public class Main {
    public static void main(String args[])
    {
        // creating two objects t1 & t2 of MyThread
        MyThread t1 = new MyThread("First  thread");
        MyThread t2 = new MyThread("Second thread");
        try {
            Thread.sleep(500);
            t1.stop(); // stopping thread t1
            t2.stop(); // stopping thread t2
            Thread.sleep(500);
        }
        catch (InterruptedException e) {
            System.out.println("Caught:" + e);
        }
        System.out.println("Exiting the main Thread");
    }
}

2.アトミックブールフラグを使用する

        Runnableインターフェースを実装するクラスを作成します。このクラスには、AtomicBooleanフラグとstopメソッドがあります。

package com.algorithm.demo.thread;

import java.util.concurrent.atomic.AtomicBoolean;

public class MyThreadDemo implements Runnable
{
    // to stop the thread
    private final AtomicBoolean running = new AtomicBoolean(false);

    private String name;
    Thread t;

    public MyThreadDemo(String threadname)
    {
        name = threadname;
        t = new Thread(this, name);
        System.out.println("New thread: " + t);
        t.start(); // Starting the thread
    }

    // execution of thread starts from run() method
    public void run()
    {
        running.set(true);
        int i = 0;
        while (!running.get()) {
            System.out.println(name + ": " + i);
            i++;
            try {
                Thread.sleep(100);
            }
            catch (InterruptedException e) {
                System.out.println("Caught:" + e);
            }
        }
        System.out.println(name + " Stopped.");
    }

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

        スレッドを呼び出して作成し、stopを呼び出してAtomicBooleanの値を変更します。 

@Test
void thread_stop_with_bool()
{
    // creating two objects t1 & t2 of MyThread
	MyThreadDemo t1 = new MyThreadDemo("First  thread");
	MyThreadDemo t2 = new MyThreadDemo("Second thread");
	try {
		Thread.sleep(500);
		t1.stop(); // stopping thread t1
		t2.stop(); // stopping thread t2
		Thread.sleep(500);
	}
	catch (InterruptedException e) {
		System.out.println("Caught:" + e);
	}
	System.out.println("Exiting the main Thread");
}

2. Thread.interrupt()メソッドを使用します

        スレッドでinterrupt()メソッドを呼び出すとき。

        1.スレッドがブロック状態(スリープ、待機、参加など)の場合、スレッドはすぐにブロック状態を終了し、InterruptedExceptionをスローします。
        2.スレッドが通常のアクティブ状態にある場合、スレッドの割り込みフラグはtrueに設定されます。割り込みフラグが設定されているスレッドは、影響を受けずに正常に実行され続けます。

        ブロッキングメソッドを呼び出すときにInterruptedException例外を適切に処理すると、スレッドはキャッチ後に終了します。

package com.algorithm.demo.thread;

import java.util.concurrent.atomic.AtomicBoolean;

public class ControlSubThread implements Runnable {

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

    // ...

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

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

    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);
    }
}

3.まとめ

        スレッドを中断したい場合。

        1.割り込みフラグが複数のスレッドで使用されない場合は、ブールフラグを使用できます。それ以外の場合は、AtomicBooleanフラグを使用します(状況に応じて静的を使用するかどうかを検討してください)。

        2.タスクを正常に実行する場合は、スレッドの割り込みフラグビットを頻繁に確認してください。割り込みフラグが設定されている場合は、スレッドが自動的に停止します。

        3.ブロッキングメソッドを呼び出すときにInterruptedExceptionを正しく処理します。(スレッドはcatch例外の後で終了します。)

おすすめ

転載: blog.csdn.net/bashendixie5/article/details/123507783