2013-02-15 9 views
17

固定レートで実行するタスクをスケジュールするScheduledThreadPoolExecutorがあります。私はタスクが「成功する」まで最大10回の指定遅延で実行したい。その後、私はタスクを再試行したくありません。だから、基本的には、スケジューリングされたタスクの実行を停止する必要がありますが、ScheduledThreadPoolExecutorをシャットダウンする必要はありません。どのように私はそれをやろうと思った?完了したら、ScheduledThreadPoolExecutorでタスクを停止する方法

は、ここではいくつかの擬似コードだ -

public class ScheduledThreadPoolExecutorTest 
{ 
    public static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(15); // no multiple instances, just one to serve all requests 

    class MyTask implements Runnable 
    { 
    private int MAX_ATTEMPTS = 10; 
    public void run() 
    { 
     if(++attempt <= MAX_ATTEMPTS) 
     { 
     doX(); 
     if(doXSucceeded) 
     { 
      //stop retrying the task anymore 
     } 
     } 
     else 
     { 
     //couldn't succeed in MAX attempts, don't bother retrying anymore! 
     } 
    } 
    } 

    public void main(String[] args) 
    { 
    executor.scheduleAtFixedRate(new ScheduledThreadPoolExecutorTest().new MyTask(), 0, 5, TimeUnit.SECONDS); 
    } 
} 

答えて

28

実行このテストは、1 2 3 4 5を印刷し、素敵な糸の外にキャンセル

public class ScheduledThreadPoolExecutorTest { 
    static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(15); // no 
    static ScheduledFuture<?> t; 

    static class MyTask implements Runnable { 
     private int attempt = 1; 

     public void run() { 
      System.out.print(attempt + " "); 
      if (++attempt > 5) { 
       t.cancel(false); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     t = executor.scheduleAtFixedRate(new MyTask(), 0, 1, TimeUnit.SECONDS); 
    } 
} 
+0

ありがとうございます!私は予定されていることを知っていましたが、私はこの方法を使用しようとしていました。 t = executor.scheduleAtFixedRate(new MyTask()、0、1、TimeUnit.SECONDS); t.cancel(true);明白な理由のために決して働かなかったであろう 。タスクの実装内でタスクをキャンセルするのは正しいことです。 – mystarrocks

+0

ありがとうございます。これは助けになりました。興味深いことに、この例は決して終了しません。私はあなたがエグゼキュータのシャットダウンを必要とすると思います – Kirby

+0

かわりに、CancellationExceptionのキャッチブロック内に 't.get()'とエグゼキュータのシャットダウンが必要です – Kirby

5

を停止します。

public class ScheduleTest { 

    @Test 
    public void testCancel() throws Exception { 
     final ScheduledThreadPoolExecutor EXECUTOR = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(2); 
     ScheduledFuture f1 = EXECUTOR.scheduleAtFixedRate(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println("Im alive 1"); 
      } 
     }, 0, 1, TimeUnit.SECONDS); 
     ScheduledFuture f2 = EXECUTOR.scheduleAtFixedRate(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println("Im alive 2"); 
      } 
     }, 0, 2, TimeUnit.SECONDS); 

     Thread.sleep(10000); 
     f1.cancel(true); 
     System.out.println("f1 cancel"); 
     Thread.sleep(10000); 
     f2.cancel(false); 
     System.out.println("f2 cancel"); 
     Thread.sleep(10000); 
    } 
} 

時にはスレッドはできませんでしたキャンセルされました。これは通常volatile boolean isCancelled;

+1

これのために多くの問題に直面している間にこれを見ているニースの例....ありがとう:) – Luffy

2

CountDownLatchの代替方法です。スレッドが完了したら、ラッチのcountDown()を呼び出します。すべてのスレッドが完了するまで、呼び出しスレッドはlatch.await()を呼び出します。その時点でExecutorService.shutdownNow()を呼び出して、メインスレッドがゾンビに変わらないようにします。

import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

public class ScheduledThreadPoolExecutorTest { 

    static int i = 0; 

    public static void main(String[] args) throws Exception { 
    final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); 
    final CountDownLatch latch = new CountDownLatch(1); 
    executor.scheduleAtFixedRate(() -> { 
     System.out.println(++i); 
     if (i > 4) { 
      latch.countDown(); 
     } 
    }, 0, 100, TimeUnit.MILLISECONDS); 
    latch.await(); 
    executor.shutdownNow(); 
    } 
} 
関連する問題