スレッドの起動と安全な終了

1. スレッドの開始

スレッドを開始するには 2 つの方法があります。1 つは Thread クラスを継承する方法、もう 1 つは次のように Runable インターフェイスを書き換える方法です。
ここに画像の説明を挿入


1.1、スレッド

Threadによるスレッド作成については、Javaマルチスレッドにおけるスレッド作成機能が既に紹介されているので、ここでは詳しく説明しません。


1.2、実行可能

実際には、Runnable と Thread の間には、インターフェイスとクラスの違いである本質的な違いはありませんが、Runnbale を書き換える場合でも、Thread を介してスレッドを開始する必要があります。


Java では多重継承が許可されていないため、Runnable を使用することで単一継承の制限によって引き起こされる問題を回避できます。


1.3、呼び出し可能

Runnable インターフェイスには戻り値がないため、一部のシナリオで戻り値が必要な場合は、Callable インターフェイスを使用する必要があります。

public class App {
    
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    
        FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
        new Thread(futureTask).start();
        System.out.println(futureTask.get());
    }
}

class MyCallable implements Callable<String> {
    
    
    @Override
    public String call() throws Exception {
    
    
        return "success";
    }
}

クラスを使用しFutureTaskて実行します。FutureTask クラスは Future インターフェイスと Runnable インターフェイスを同時に実装しているため、スレッドによって Runnable として実行でき、Callable の戻り値を取得する Future としても使用できます。
ここに画像の説明を挿入

なお、戻り値を取得する際にはFutureTask.get()ブロッキングメソッドが使用されており、このメソッドが呼び出されると後続のコードはブロックされ、Callableメソッドが実行された後でのみ実行を続行できます。


2つ目はスレッドの停止です

多くの場合、スレッドを停止する必要がある場合があります。Java の API にはsuspend()resume()stop()などのメソッドがあり、その機能はスレッドの一時停止、スレッドの実行の再開、スレッドの終了です。
ここに画像の説明を挿入

ただし、これら 3 つのメソッドはスレッドに対して即時操作を実行するため、これら 3 つのメソッドは推奨されなくなったことがわかりました。たとえば、これらのメソッドはスレッドを即座に停止および一時停止しますが、スレッド内のリソースは解放されませstop()suspend()。プログラムのデッドロックの問題が発生する可能性があります。


2.1、interrupt() メソッドと isInterrupted() メソッド

スレッドは他のスレッドによって強制的に中断または停止されるべきではなく、スレッド自体によって停止される必要があります。interrupt()したがって、メソッドを使用してスレッドに中断する必要があることを通知できますが、中断するか実行を継続するかは、通知されたスレッド自体によって処理される必要があります


Interrupt() メソッドを呼び出すと、スレッドの割り込みフラグが true に設定されるだけで、割り込みは強制されません。同時に、Java には、スレッドが中断されているかどうかを問い合わせるメソッドisInterrupted()と静的メソッドも提供されていますThread.interrupted()。違いは、静的メソッドはスレッドの中断された状態を問い合わせた後に状態を false に設定することです。
ここに画像の説明を挿入

次のテストでは、スレッドが中断されているかどうかを問い合わせる静的メソッド Thread.interrupted() が、中断フラグを false に変更することがわかります。また、ここで表示するためにメイン スレッドが直接使用されます。新しいスレッドはテスト用に作成されます。最初にスレッドを開始して実行し続ける必要があります。それ以外の場合、クエリは false でなければなりません
ここに画像の説明を挿入


また、キャンセル フラグをカスタマイズしてスレッドの実行を一時停止することはお勧めできません。run() メソッドにブロッキングがある場合、カスタムキャンセルフラグを検出できないため、スレッドはキャンセルフラグをチェックする前にブロッキング呼び出しから戻る必要があるためです。


2.2、InterruptedException 例外

スレッドがブロック状態にあり (たとえば、スレッドが thread.sleep()、thread.join()、thread.wait() などを呼び出した場合)、操作を中断するために割り込みメソッドが呼び出された場合、InterruptedException が発生します。がスローされますが、例外がスローされた直後に、スレッドの割り込みフラグ ビットがクリアされ、つまり false にリセットされます。
ここに画像の説明を挿入


したがって、InterruptedException 例外が発生しています。スレッドを中断する必要があることを確認した場合は、ここで再度中断フラグを設定する必要があります。
ここに画像の説明を挿入


2.3、今後の課題

cancel()Future インターフェイスを実装する FutureTask は、割り込み信号を送信できるなど、他の割り込みメソッドも提供します。


また、FutureTask クラスには、タスクが完了したかどうかを判断するためのisDone()isCancelled()、タスクがキャンセルされたかどうかを判断するための と が用意されています。
ここに画像の説明を挿入

  • cancel(boolean):タスクがキャンセルされ、true を返します。それ以外の場合は false を返します。
    1. cancel(true): 実行中のタスクを中断します。
    2. cancel(false): すでに実行中のタスクを中断しません。
  • isDone():タスクが完了したか、正常終了か異常終了かキャンセルか、trueを返します。
  • isCancelled():タスクが完了前にキャンセルされたかどうか

おすすめ

転載: blog.csdn.net/rockvine/article/details/124972509