1

スレッドを中断することになっているメソッドがありますが、そうではありません。whileメソッドで中断されたスレッドを常にチェックしてスレッドを停止する必要がありますか?いつでもスレッドを終了するにはどうすればよいですか?

solverTh = new Thread(new Runnable() {
        @Override
        public void run() {
            while(somethingistrue){
                //do lot of stuff here for long time
            }
        }
    });
    solverTh.start(); 
}

public void terminate(){
    if(solverTh != null){
        solverTh.interrupt();
    }
}

「たくさんのもの」は関係ないと思っていたよりも大丈夫ですが、それよりも投稿します。それはopenGL操作を行い、ブール変数「終了」を現在機能するコードに追加しました。より良い解決策を見つけたかっただけです:(glcはGLCanvasであり、rotmultiplecubeメソッドは3つのオブジェクトを回転させます)とにかく問題を解決しました今、答えてくれてありがとう。

            terminated = false;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex);
            }

            int colorToBeSolved = Statics.RED_BLUE_TABLE[stateToBeSolved];
            System.out.println(stateToBeSolved + "," + colorToBeSolved);
            if(entities[0].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.FIRST_ROW, Statics.DOWN);
            }
            if(entities[1].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.SECOND_COL, Statics.RIGHT);
            }
            if(entities[2].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.THIRD_COL, Statics.RIGHT);
            }
            if(entities[3].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.SECOND_ROW, Statics.DOWN);
            }
            if(entities[6].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.THIDR_ROW, Statics.DOWN);
            }

            for(int i = 0; i < 9; ++i){
                int col = i % 3;
                int row = 3 + i/3;
                while(entities[i].getState() != stateToBeSolved){
                    for(int j = 0;j < 2; ++j){
                        if(entities[i].getState() != stateToBeSolved){
                            if(terminated) return;
                            fullRotate(col, Statics.LEFT);
                            if(terminated) return;
                            fullRotate(row, Statics.UP);
                            if(terminated) return;
                            fullRotate(col, Statics.RIGHT);
                            if(terminated) return;
                            fullRotate(row, Statics.DOWN);
                        }
                    }
                    for(int j = 0;j < 2; ++j){
                        if(entities[i].getState() != stateToBeSolved){
                            if(terminated) return;
                            fullRotate(col, Statics.RIGHT);
                            if(terminated) return;
                            fullRotate(row, Statics.UP);
                            if(terminated) return;
                            fullRotate(col, Statics.LEFT);
                            if(terminated) return;
                            fullRotate(row, Statics.DOWN);
                        }
                    }
                }
            }
        }

および全回転法:

private void fullRotate(int selectionIndex, int direction){
    for(int i = 0; i < 9; ++i){
        glc.rotMultipleCubeSlow(selectionIndex, direction);
        try {
            Thread.sleep(20);
        } catch (InterruptedException ex) {
            terminate();
        }
    }
    glc.setMovesText(selectionIndex, direction);        
    glc.setMultipleStateAndColorsByTable(selectionIndex, direction);
    glc.isEntitiesRight();
}
4

5 に答える 5

2
while(somethingistrue !Thread.currentThread().isInterrupted()){
  //do lot of stuff here for long time
}

IOをブロックするために機能する必要はありません。ダーティトリックを使用します。Thread.interrupt()をオーバーライドしてIOオブジェクトを閉じ、IOExceptionを発生させます。これは、適切に処理された場合、スレッド実行メソッドを終了する可能性があります。

于 2012-04-09T11:43:55.270 に答える
1

洗練された解決策は、fullRotate()メソッドを変更してInterruptedExceptionをスローすることです。

private void fullRotate(int selectionIndex, int direction)
       throws InterruptedException{
    for(int i = 0; i < 9; ++i){
        glc.rotMultipleCubeSlow(selectionIndex, direction);
        Thread.yield();
    }
    glc.setMovesText(selectionIndex, direction);        
    glc.setMultipleStateAndColorsByTable(selectionIndex, direction);
    glc.isEntitiesRight();
}
  • Thread.interrupt()を呼び出すと、それをスローするメソッド(この場合はThread.sleep()またはThread.yield())が呼び出されたときに、InterruptedExceptionが発生します。これは、最良のアプローチは実際に計算を中断するためにそれを使用することであることを意味します。
  • Thread.interrupt()に即座に応答したい場合は、Thread.currentThread()。isInterrupted()をチェックする必要があります。
  • if(終了)returnをエーテルで削除できます。または、Thread.currentThread()。isInterrupted()チェックに置き換えます。fullRotate()からThread.sleep(20)/ Thread.yield()がInterruptedExceptionをスローするため、削除しても問題ありません。また、コードは、あちこちで(終了した)場合、これらすべてがなくてもクリーンになります。
  • Thread.sleep(20)の代わりにThread.yield()を使用してください。明らかに、あなたは20ミリを置くので、あなたは眠りたくありません。20ミリは、コンテキストスイッチのタイムクォンタムに非常に近いです。スレッドは多かれ少なかれスリープ状態になります。理由もなくスリープ状態にしたくないので、yield()を使用します。

スレッドrun()は次のようになります。

solverTh = new Thread(new Runnable() {
    @Override
    public void run() {
        while(somethingistrue && 
              !Thread.currentThread().isInterrupted()) {
            try {
                //do lot of stuff here for long time
            } catch (InterruptedException ex) {
                // handle stop processing 
            }
        }
    }
});
solverTh.start(); 

また、以下からtrycatchを削除する必要があります。

        try {
            Thread.sleep(2000);
        } catch (InterruptedException ex) {
            Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex);
        }
于 2012-04-09T13:08:04.170 に答える
0

スレッドを中断する唯一の方法は、スレッドを終了させることです。デッドロックの可能性があるため、Javaでは完全な中断は実装されていません。したがって、スレッドコードは次のようになります。

solverTh = new Thread(new Runnable() {
    @Override
    public void run() {
        while(somethingistrue) 
            // Do a little stuff here
        }
    }
});
solverTh.start(); 

そしてsomethingistrue、スレッドが割り込むための一種のシグナルです。

于 2012-04-09T11:39:12.627 に答える
0

あるスレッドの実行を別のスレッドから確実に停止できるのはOSだけです。したがって、多くの選択肢はありません。

1)スレッドにそれ自体を停止するように信号を送ります。このスキームは、スレッドが何をしているかによって異なります。別のプロセッサで実行されている場合、またはブロックを解除できないブロック呼び出しでスタックしている場合(注-多くのブロック呼び出しは早期に戻るように説得できます)、問題が発生する可能性があります。

「たくさんのこと」は何をしているのですか?

2)OS呼び出しを使用してスレッドを終了します。これは、スレッドの機能によっては、実行可能なオプションになる可能性があります。重要なリソースのパブリックロックを保持しているときにスレッドを終了する可能性がある場合(たとえば、malloc()の途中で、メモリマネージャーがロックされている場合)、問題が発生する可能性があります。この方法でスレッドを安全に中止するには、スレッドが何をしているのかを確認する必要があります。

3)別のプロセスを使用して「スタッフ」を実行します。これは明らかに問題なく機能しますが、通常、データを渡して結果を返すためのプロセス間通信は遅くて苦痛を伴います。

4)スレッドを終了する必要がないようにアプリを設計します。一部のアプリは、アプリのシャットダウン時を除いてスレッドを終了する必要がないため、問題はありません。OSは何でも停止できます。アプリの実行中にスレッドを「停止」する必要があり、CPUを大量に消費する長時間の操作を実行している場合、または長時間、場合によっては不確定な期間ブロックされている場合は、優先度を最小/アイドルに設定してスレッドを「孤立」させます。最終的に消滅するためにそれを残すことは別の一般的なアプローチです。

考えられる最悪のシナリオは、メモリマネージャまたは他のパブリックロックを使用するスレッドが長時間実行されていることです。おそらく、ライブラリで、何をしているのか正確にわからず、フックできず、読み取り/書き込みができません。データを「孤立させる」とは、別のスレッドがデータの使用を開始できないことを意味します。あなたは本当に頑固で、アプリを終了して再起動する必要があるかもしれません。スレッドがそのような状態になる可能性のある設計は避けるのが最善です:)

5)1つ忘れてください-スレッドが取得できるデータを使用している場合、NULL、0、MaxInt、またはその他のbodgeのようなものに設定すると、長いものを実行しているスレッドで例外が発生する可能性があります。実行が長いものからバブルアウトした場合、スレッドは例外ハンドラーで割り込み状態をチェックし、設定されている場合は終了できます。

于 2012-04-09T11:40:45.377 に答える
0

スレッドが実行されている場合(CPUサイクルを消費している場合)、デフォルトでは(自動的に)応答しませんThread.interrupt()。これを明示的に行うには、コードを記述する必要があります。

//do lot of stuff here for long time2つ以上のステップに分割し、これらのステップの間に挿入して、Thread.currentThread().isInterrupted()-がtrueの場合はブレークアウトし、それ以外の場合は続行します。これはあなたが望むことを達成するための唯一の安全な方法です。

それは長期的なものが何であるかに依存します、あなたはステップを設計し、中断とブレイクアウトをチェックするのに最適な時期を決定する必要があります。

于 2012-04-09T11:48:45.557 に答える