停止するスレッド、ベストプラクティスを中断

スレッドの権利を停止する方法

1の原理を説明

原理の説明:使用すると、中断するというよりも、必須、通知すること。Javaスレッドの原則はどのように停止されていますか?

Javaでは、スレッドを停止するための最良の方法は、割り込み割り込みを使用しているが、これは単にスレッドは、「あなたが実行を停止する必要がある」終了することが通知され、スレッド自体かどうか、いつに決定する(決定する力を終了しますされますパーティやコンベンションの良いコーディング仕様に準拠するためにパーティーを停止する停止要求に応じて、)を停止します。

簡単なタスクとスレッドを開始します。時間のほとんどは、我々は彼らが最後まで実行してみましょうか、彼らは自分自身で停止させます。しかし、時には我々は、ユーザが操作またはサービスが迅速にシャットダウンする必要がキャンセル、または不足するまたは間違ったかもしれないので、タスクの終了、またはスレッドを進めたいです。

タスクおよびスレッドセーフにするには、迅速かつ確実に停止は容易な作業ではありません。Javaは安全にスレッドを終了する任意のメカニズムを提供しません。しかし、それは協力メカニズムである割り込み(中断)を提供し、あるスレッドが別のスレッドの現在の作業を終了させることができます。

この協調的アプローチが必要であり、我々はほとんどのタスク、スレッドを望んでいないか、すぐにサービスを停止し、それはすぐに矛盾した状態でデータ構造を共有して停止するためあなたは、タスクおよびサービスの準備に停止する必要があり、共同の方法を使用するときは対照的に、彼らは最初に、現在閉じる前に行われている作業がクリアされます。これは、より高い柔軟性を提供し、コード自体よりも、コードのタスクは、より明確にクリーンアップ作業を実行する方法を取り消し要求を発行したので

プロセスが複雑になるなどの生命の終わりには、(の-ライフサイクルエンド)は、問題のタスクだけでなく、サービスの設計とプログラムの実施を行いますが、これはしばしば見落とされプログラミング要素で非常に重要です。かろうじてソフトウェアに同梱のソフトウェアの良い行動との間の1つの大きな違いは、決算やキャンセル処理の失敗のハンドリングを向上させることができる非常に行儀のソフトウェアです。

この章では、キャンセルや中断を達成するために、様々なメカニズムを提供し、どのように取り消し要求に応答するためにそれらを可能にするために、タスクおよびサービスを記述すること

2.ベストプラクティス:スレッドの権利を停止する方法

2.1スレッドは通常、どのような状況で停止します

1、run()メソッドの実行が終了し
2、例外、およびキャッチされていないスレッドがあります。
スレッドが停止した後、占有リソースがJVMを回復することになります。

2.2正しい停止方法:中断

通常の状況で停止する方法2.2.1

package stopthreads;

/**
 * 描述: run()方法内没有sleep()和wait()方法时,停止线程。
 */

public class RightStopThreadWithoutSleep implements Runnable{

    public static void main(String[] args) {
        Thread thread = new Thread(new RightStopThreadWithoutSleep());
        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.interrupt();

    }
    @Override
    public void run() {
        int num = 0;
        while (num <= Integer.MAX_VALUE / 2){
            if (!Thread.currentThread().isInterrupted() && num % 10000 == 0) {
                System.out.println(num + "是10000的倍数");
            }
            num++;
        }
        System.out.println("任务结束了。");
    }
}

复制代码

注意: thread.interrupt();必須ではありません割り込みスレッドを、中断したスレッドに存在し協力しなければなりません。
すなわち:サブスレッドのコードを追加する必要があります。!Thread.currentThread().isInterrupted()

どのようにスレッドを停止するには2.2.2がブロックされることがあります

package stopthreads;

import static java.lang.Thread.*;

public class RightStopThreadWithSleep {
    
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = ()->{
            int num = 0;
            while (num <= 300){
                if (num % 100 == 0 && !currentThread().isInterrupted()){
                    System.out.println(num + "是100的整数倍");
                }
                num++;
            }
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        Thread thread = new Thread(runnable);
        thread.start();
        Thread.sleep(500);
        thread.interrupt();
    }

}

复制代码

結果は以下の通りであります:

2.2.3各反復後のスレッドがブロックされている場合

package stopthreads;

import static java.lang.Thread.currentThread;
import static java.lang.Thread.sleep;

/**
 * 描述:如果在执行过程中,每次循环都会调用sleep()或wait()等方法,那么...
 */
public class rightStopThreadWithSleepEveryLoop {

    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = ()->{
            int num = 0;
            try {
                while (num <= 10000){
                    if (num % 100 == 0 && !currentThread().isInterrupted()){
                        System.out.println(num + "是100的整数倍");
                    }
                    num++;
                    sleep(10);
                }
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        };

        Thread thread = new Thread(runnable);
        thread.start();
        Thread.sleep(5000);
        thread.interrupt();
    }

}

复制代码

try-catchの問題を同時に内:

package stopthreads;

import static java.lang.Thread.currentThread;
import static java.lang.Thread.sleep;

public class CantInterrupt {

    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = ()->{
            int num = 0;

                while (num <= 10000){
                    if (num % 100 == 0 && !currentThread().isInterrupted()){
                        System.out.println(num + "是100的整数倍");
                    }
                    num++;
                    try {
                        sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

        };

        Thread thread = new Thread(runnable);
        thread.start();
        Thread.sleep(5000);
        thread.interrupt();
    }

}

复制代码

try-catch位置を変更して、結果は完全に異なっています:

注意: :でもに追加 && !currentThread().isInterrupted() まだ効果なし!
理由: 設計時にThreadクラス、睡眠は()中断するために呼び出す、割り込みマーカーが自動的にクリアされます!

両方の実際の開発プラクティス2.3のベスト

2.3.1ベストプラクティス1:リファレンス:送信がブロックされた(署名方式は、例外をスロー)

さんが少しエピソードを追加してみましょう:間違って例外を処理する、方法が直接に呼び出されたInterruptExceptionアウトキャッチ、これは例外があることを認識することができません上位のコールにつながる、飲み込むために例外を置くために、低レベルのアプローチと同等です。
正しいアプローチは、次のようになります。例外をスロー、例外処理が本当に機能がそのそれを呼び出すと呼ばれるべきです。
次のようにエラー・コードは次のとおりです。

package stopthreads;

/**
 * 描述:  catch了InterruptionException之后的优先选择:在方法签名中抛出异常。
 * 那么,在run()中就会强制try-catch。
 */
public class RightWayStopThreadInProduction implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new RightWayStopThreadInProduction());
        thread.start();
        thread.sleep(1000);
        thread.interrupt();
    }

    @Override
    public void run() {
        while(true){
            System.out.println("go");
            throwInMethod();
        }
    }

    private void throwInMethod() {

        /**
         * 错误做法:这样做相当于就把异常给吞了,导致上层的调用无法感知到有异常
         * 正确做法应该是,抛出异常,而异常的真正处理,应该叫个调用它的那个函数。
         */
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

复制代码

異常なエラー処理は、スレッドが停止することはできません原因:


正しいアプローチ:例外をスローし、例外処理が本当に機能がそのそれを呼び出すと呼ばれるべきです。
低レベルのメソッドが例外をスローし、呼び出し側は、唯一のtry / catchを上にして囲みます。

次のように正しいコードは次のとおりです。

package stopthreads;

import static java.lang.Thread.sleep;

/**
 * 描述:  catch了InterruptionException之后的优先选择:在方法签名中抛出异常。
 * 那么,在run()中就会强制try-catch。
 */
public class RightWayStopThreadInProduction implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new RightWayStopThreadInProduction());
        thread.start();
        sleep(1000);
        thread.interrupt();
    }

    @Override
    public void run() {
        while(true){
            System.out.println("go");
            throwInMethod();
        }
    }

    private void throwInMethod() throws InterruptedException {

        /**
         * 错误做法:这样做相当于就把异常给吞了,导致上层的调用无法感知到有异常
         * 正确做法应该是,抛出异常,而异常的真正处理,应该叫个调用它的那个函数。
         */
       /* try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/

       sleep(2000);

    }
}

复制代码

要約:

2.3.2ベストプラクティス2:にしたくないか、配信することができません。再開が中断(再び男が復元手動で中断)

下のプロセスでは、キャッチを試みるかもしれませんが、追加する必要があります)にThread.currentThread()(中断;

package stopthreads;

import static java.lang.Thread.sleep;

public class RightWayStopThreadInProduction2 implements Runnable{

    @Override
    public void run() {

        while(true){
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("线程中断");
                break;
            }
            reInterrupt();
        }

    }

    private void reInterrupt() {

        try {
            sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new RightWayStopThreadInProduction2());
        thread.start();
        sleep(1000);
        thread.interrupt();
    }
}

复制代码

結果:

概要:あなたが行う方法を、中断を投げることができない場合は?

あなたがしたくないか、配信できない場合InterruptedException(runメソッドは、プロセスを聞かせていないとき、例えばthrows InterruptedException)、その後、catch節で呼び出すように選択する必要がありThread.currentThread() interrupt()、まだちょうど中断された後の実行でチェックすることができるようにするために、割り込み状態セットを復元します。割り込み状態を検出できるようにスレッドは、睡眠中に中断、及びキャッチキャッチによって割り込み及び割り込み状態をリセットされた上記特定コードと、次のサイクル、正常終了。

割り込みをマスクするべきではありません

2.4利益を停止する権利

3.既製誤差法を停止

4.重要なソース解析関数

5.よくあるインタビューの質問

おすすめ

転載: juejin.im/post/5d6c8e23f265da03c23eedb8