2012-04-09 7 views
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); 
         } 
        } 
       } 
      } 
     } 

とfullrotate方法:

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(); 
} 
+0

1):

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

また、あなたは以下から試しキャッチを削除する必要があなたは、Javaのメーカが(少なくとも安全ではない)ことができないと言うことを達成することができると思いますか? 2) '//長い間ここにたくさんのものを置く'コードは言葉よりも大声で話す。もっと早く助けを求めるには、[SSCCE](http://sscce.org/)を投稿してください。 –

+0

チェックしましたか:http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html – anuragsn7

答えて

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()をチェックする必要があります。
  • return(if) Thread.currentThread()。isInterrupted()checkに置き換えてください。 fullRotate()のThread.sleep(20)/Thread.yield()がInterruptedExceptionをスローするため、削除が正常に行われます。また、これらのすべてがなくても、コードはきれいになります。
  • Thread.sleep(20)の代わりにThread.yield()を使用します。 20ミリ秒を置くので、明らかにあなたは眠りたくありません。 20ミリスはコンテクストスイッチ時間量子に非常に近い。スレッドは、より多くの、またはより少ないスリープ状態になります。あなたは何の理由もなく寝ることを望んでいないので、yield()を使用してください。

あなたのスレッドの実行()は次のようになります。*「どのように私はちょうど終了することができます

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

catchブロックのInterruptedステータスをリセットすることを確認してください。そうしないと、whileループが実行され続けます。 –

+0

これははるかによく聞こえる、ありがとう!私はそれを試してみます –

+0

@FerencDajkaは答えを受け入れることを忘れないでください:) – hidralisk

0

スレッドを中断する唯一の方法は、それ自体を終了することです。デッドロックの可能性があるため、Strightforward割り込みはJavaでは実装されていません。だからあなたのスレッドのコードは次のように見なければならない:

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

そしてsomethingistrueは中断するスレッドのための信号の一種です。

+0

「小さなもの」がCPUを集中的に使用する単一のタスクであればどうなりますか?それが完了するまで、状態は見られません – mbatchkarov

+0

はい、そのようなタスクは常に痛みです。しかし、とにかく、回避策が見つかることがあります。たとえば、このCPU集約型タスクが別のプロセスである場合、スレッドは各時間間隔ごとに終了条件をチェックし、必要に応じて終了させることができます(プロセスは簡単に終了できます)。 –

0

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

1)スレッド自体に停止を通知します。このスキームは、スレッドが何をしているかによって異なります。別のプロセッサ上で実行されている場合や、ブロッキングコールに固執している場合はブロック解除することはできません(多くのブロッキングコールが早期に返されることに注意してください)。

「たくさんのもの」は何をしていますか?

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

3) 'stuff'を実行するために別のプロセスを使用します。これは明らかに正常に機能しますが、通常、データを渡して結果を返すための、遅くて痛いプロセス間通信が必要です。

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

最悪の場合は、メモリマネージャや他のパブリックロックを使用しているスレッドが、おそらくライブラリの中で何をしているのかわからない場合や、 「孤立(orphaning)」とは、別のスレッドがデータの使用を開始できないことを意味するようにデータを読み書きします。あなたは本当にstuftしているし、アプリケーションを終了して再起動する必要があります。

5)スレッドが取得できるデータを使用していて、何かをNULL、0、MaxInt、または他のボギーのようなものに設定している場合は、設計を避けるだけです。長いものを実行しているスレッドで例外が発生する可能性があります。実行が長いものから飛び出すと、スレッドは例外ハンドラで中断状態をチェックし、設定されていれば終了することができます。

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

IOのブロックには対応していません。ダーティトリックを使用する:Thread.interrupt()close IOオブジェクトをオーバーライドする。適切に処理されるとスレッド実行メソッドを終了させるIOExceptionを引き起こす。

+0

+1はい - 汚れたトリックの1つ:)もう一つは、フォルダーウォッチャーAPIが監視されたフォルダーに一時ファイルを書き込むことによって戻るように強制しています。 UDPソケット読み取り/ TCPの受け入れは、ローカルクライアント接続を開くか、空のUDPメッセージを送信することによって戻ることができます。 –

+0

くそー、これはサードパーティのライブラリのための非常に便利な汚いトリックです!どうもありがとうございます! – parasietje

0

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

//do lot of stuff here for long timeを2つ以上のステップに分割し、Thread.currentThread().isInterrupted()をチェックしてください。そうでない場合は、続行してください。これは、あなたが望むものを達成するための安全な方法です。

長時間実行されているものがあるかどうかによって、ステップを設計し、中断や中断をチェックするのが最善のタイミングを判断する必要があります。

関連する問題