3

フォームの処理ループがあります

while (true) {
    doWork();
    Thread.sleep(SLEEP_INTERVAL);
}

Runnable私はこれでうまく遊ぶことができ、呼び出されたExecutorServiceときに終了するものを作りたいと思っています。ExecutorService.shutdownNow()

私はこのように書くことを目指しています:

public WorkerTask implements Runnable
{
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            doWork();
            try {
                Thread.sleep(SLEEP_INTERVAL);
            }
            catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

ExecutorService簡単なテストでは、タスクが中断されて終了し、がシャットダウンするという点で少なくとも機能しているように見えdoWork()ますsleep。(作業の量doWork()と大きSLEEP_INTERVALさを変えることで、割り込みが発生する場所をほぼ制御できます)。

しかし、グーグルで検索すると、 と を使用Thread.interrupted()した例が表示されThread.currentThread().isInterrupted()ます。前者は中断フラグをクリアし、後者はそれを残すことは理解していますが、他に気にする必要がある違いはありますか?

Thread.currentThread().isInterrupted()orの結果が変数Thread.interrupted()に格納され、volatileその変数がwhileループ テスト条件として使用されるバージョンも見られます。それは単なるスタイルですか、それともそうする必要がありますか? 私が書いたものでは、割り込みフラグが設定されたとき(スレッドがライブのときに受信されるかInterruptedException、フラグをキャッチして再アサートするかによって)とThread.currentThread().isInterrupted()、ループテスト?

4

3 に答える 3

3

あなたのコードは私にはうまく見えます。追加の揮発性変数を導入すると、不必要に複雑になります。割り込みステータスが仕事をします。

Java Concurrency in Practiceで推奨されるタスクの割り込み処理方法は、 をスローするInterruptedException(タスクがCallableでなく である場合に実行Runnable可能) か、割り込みステータスが設定されていることを確認してタスクを終了することです。できるだけ速くに。あなたのコードはそれをうまくやっています。

于 2012-07-28T06:36:26.113 に答える
0

ScheduledExecutorService要件に一致するかどうかを確認してください。

 class BeeperControl {
    private final ScheduledExecutorService scheduler =
      Executors.newScheduledThreadPool(1);

    public void beepForAnHour() {
      final Runnable beeper = new Runnable() {
        public void run() { System.out.println("beep"); }
      };
      final ScheduledFuture<?> beeperHandle =
        scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
      scheduler.schedule(new Runnable() {
        public void run() { beeperHandle.cancel(true); }
      }, 60 * 60, SECONDS);
    }
  }}
于 2012-07-28T08:59:23.413 に答える
0

基本的に、java.util.concurrentここでライブラリを利用する必要があります。 経由でタスクを送信してからExecutorService.submit()、 のようなブロッキング メソッドを呼び出す必要があります。そうすればFuture.get()、これらのメソッドができるだけ早く割り込みに応答することを確認できますExecutionException()。おそらく、そのスレッドを取り除く必要があります。 .sleep() は何もしていないためです。できるだけ早く割り込みをスニッフィングしたい場合や、タスクが無限に何かを実行している場合に備えて、タイムアウトを待ちたい場合もあります。そのため、タスクが TimeOutException で終了した場合、タスクはその Future を介してキャンセルされます。cancel()完了したタスクをキャンセルしても効果がないため、無条件に呼び出します。その場合、次のようなことができます:

 public static void main(String[] args) {
    WorkerTask runnable;
    TimeUnit unit;
    Future<?>   task = executor.submit(workerTask);
    try{
      task.get(timeout,unit);
    } catch(TimeoutException e){

    }catch(ExecutionException e){
        throw e.getCause();  
    } finally{
      //Harmless if the task already completed
      task.cancel(true);
    }
  }
}      
于 2012-07-30T06:53:00.593 に答える