2011-06-27 16 views
20

、私は(シングルスレッドで)TimerScheduledThreadPoolExecutorを見てreference for Executors.newSingleThreadScheduledExecutor()で、それが言うので、後者を使用することにしました:例外がスローされた後にScheduledExecutorServiceがタスクを再度実行しないのはなぜですか?定期的なタスクを実行するための

注しかし、この単一スレッドがのために終了した場合シャットダウン前に実行中に障害が発生した場合、後続のタスクを実行するために必要に応じて新しいものが使用されます。

これは、他の操作を監視したいウォッチドッグコードの未捕捉例外に対する保護手段として使用することでした。私は以下のテストを確実にして書いたかったのですぐに失敗しました。私は間違った前提をしていたか、私のテストについて何か間違っているようですか?繰り返しタスクは、エラー状態で死亡したりもしていると想定されて捕捉されない例外をスローしたら

@Test 
public void testTimer() { 
    final AtomicInteger cTries = new AtomicInteger(0); 
    final AtomicInteger cSuccesses = new AtomicInteger(0); 

    TimerTask task = new TimerTask() { 
     @Override 
     public void run() 
     { 
      cTries.incrementAndGet(); 
      if (true) { 
       throw new RuntimeException(); 
      } 
      cSuccesses.incrementAndGet(); 
     } 
    }; 

    /* 
    Timer t = new Timer(); 
    t.scheduleAtFixedRate(task, 0, 500); 
    */ 
    ScheduledExecutorService exe = Executors.newSingleThreadScheduledExecutor(); 
    exe.scheduleAtFixedRate(task, 0, 500, TimeUnit.MILLISECONDS); 
    synchronized (this) { 
     try { 
      wait(3000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
     } 
    } 
    exe.shutdown(); 
    /* 
    t.purge(); 
    */ 
    Assert.assertEquals(cSuccesses.get(), 0); 
    Assert.assertTrue(cTries.get() > 1, String.format("%d is not greater than 1. :(", cTries.get())); 
} 
+0

私は知っている、私はものの周りにキャッチ(Throwable)をラップすることができますが、私の計画は何とか自分自身から私を保護することでした。 –

+5

このようなフレームワーク・コードでは、失敗したジョブを安全に再開できると仮定するのは問題になります。例外で失敗したということは、データがあらゆる状態のまま残っている可能性があり、仕事。 –

+3

新しいスレッドの開始についての引用は、失敗しても他のジョブの実行を継続できるようにすることです。 –

答えて

22

は、ここでは、コードです。あなたがエラー/例外を取得するために未来を調べなければ、それも黙って失敗するのはちょっとした問題です。

繰り返しタスクを強制終了したくない場合は、例外をキャッチする必要があります。


マットbは上記のコメントで指摘するように、

、それが安全に失敗したジョブを再開することができると仮定し、このようにフレームワークコードのために問題となる - それはで失敗したという事実例外は、データがどのような状態のまま残されている可能性があり、潜在的にジョブを再起動することが危険であることを意味します。

+0

これはまだ適用できますか? Springブート1.5.3では、反復タスクのデフォルトのエラーハンドラは[LOG_AND_SUPRESS_ERROR_HANDLER](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/TaskUtils.html# LOG_AND_SUPPRESS_ERROR_HANDLER)実行キューから@Scheduledを削除しません。 –

+0

例外を無視して自動的に再起動するようにコードをプログラムするのは悪い考えですが、手動で問題を修正するとスケジューラの再起動に使用できるRESTfulサービスをプログラムできますか? – jDub9

+0

@ jDub9できます。再度実行する準備ができたら、新しいExecutorServiceまたは新しいタスクを作成することに問題はありません。 –

5

マットbが挙げられます。

それは 安全に失敗したジョブを再開することができると仮定し、このようにフレームワークコードのために問題となる - それは 例外で失敗したという事実は、データが 状態の任意の並べ替えに残されている可能性がありますことを意味しジョブを再起動するのは危険です。それはそれを留意すべきである



ScheduledExecutorService

の文書で記述されているタスクのいずれかの実行が例外に遭遇した場合、その後の 実行は抑制されます。

そしてマイケルKrusseが言うように、新しいスレッドの作成についてポイントは、他のタスクが実行を継続できるようにすることです。

関連する問題