6

実行中のスレッドをすぐに停止したい。これが私のコードです:

クラス A :

public class A() {
    public void methodA() {
        For (int n=0;n<100;n++) {
        //Do something recursive
        }
        //Another for-loop here

        //A resursive method here

        //Another for-loop here

        finishingMethod();        
    }    
}

クラス B:

public class B() {
    public void runEverything() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    A a = new A();
                    a.methodA();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
       Thread thread = new Thread(runnable);
       thread.start();
    }

私の問題は、スレッドが終了する前であっても、クラス B でスレッドを停止できる必要があることです。interrupt() メソッドを試しましたが、スレッドは停止しません。スレッドを停止するシグナルとして共有変数を使用することについても聞いたことがありますが、プロセスに長い再帰的ループと for ループがあると、共有変数は効果的ではないと思います。

何か案が ?前もって感謝します。

4

5 に答える 5

13

Thread.interruptスレッドを停止しません (スレッドがスリープ状態でない限り、その場合はInterruptedExceptionがスローされます)。割り込みは基本的に、スレッドが中断されたことを示すメッセージをスレッドに送信しますが、スレッドがすぐに停止することはありません。

長いループ操作がある場合、フラグを使用してスレッドがキャンセルされたかどうかを確認するのが標準的な方法です。そのフラグmethodAを追加するように変更できるので、次のようになります。

// this is a new instance variable in `A`
private volatile boolean cancelled = false;

// this is part of your methodA
for (int n=0;n<100;n++) {
  if ( cancelled ) {
    return; // or handle this however you want
  }    
}

// each of your other loops should work the same way

次に、cancel メソッドを追加して、そのフラグを設定できます

public void cancel() {
  cancelled = true;   
}

次に、誰かが on を呼び出しrunEverythingた場合、 onBを呼び出すBことができます (変数を抽出する必要があるため、 が呼び出された 後でも変数への参照があります。cancelAABrunEverything

于 2012-08-11T01:36:31.683 に答える
3

根気よく使い続けるといいと思いますThread.interrupt()。しかし、それを機能させるために必要なことは、methodAコードを次のように変更することです。

public void methodA() throws InterruptedException {
    for (int n=0; n < 100; n++) {
        if (Thread.interrupted) {
             throw new InterruptedException();
        }
        //Do something recursive
    }
    // and so on.        
}

これは、次の点を除いて、独自の「キル スイッチ」変数を宣言して使用することと同じです。

  • 多くの同期 API、および一部の I/O API はinterrupted状態に注意を払います。
  • 行儀の良いサードパーティのライブラリはinterrupted状態に注意を払います。

現在、多くのコードが誤っ て処理されていることは事実ですInterruptedException。たとえば、それを押しつぶすことによって。(を処理する正しい方法InterruptedExceptionは、伝播を許可するか、呼び出しThread.interrupt()てフラグを再度設定することです。)ただし、反対側は、同じコードがキル スイッチを認識しないことです。だから、どちらにしても問題があります。

于 2012-08-11T03:15:51.387 に答える
1

ループまたは再帰の一部として実行フラグのステータスを確認できます。kill シグナルがある場合 (つまり、実行フラグが false に設定されている場合) は、(必要なクリーンアップの後に) 戻るだけです。

于 2012-08-11T01:35:59.887 に答える
0

他にも考えられるアプローチがいくつかあります。

1) 停止しないでください - 割り込みフラグで停止するように信号を送って、優先順位を可能な限り低く設定し、スレッドとそれが処理しているデータ オブジェクトを「孤立」させます。このスレッドで実行される操作が再度必要な場合は、別のスレッドを作成してください。

2) 処理中のデータを無効にする、破損する、名前を変更する、閉じる、またはその他の方法で破棄して、スレッドを強制的に segfault/AV にするか、他の方法で除外します。スレッドはスローをキャッチし、割り込みフラグをチェックできます。

保証なし、見たままの状態で販売...

于 2012-08-11T04:07:43.513 に答える