2013-02-15 17 views
17

Ho un ScheduledThreadPoolExecutor con cui pianifico un'attività da eseguire a una velocità fissa. Voglio che l'attività sia in esecuzione con un ritardo specificato per un massimo di dire 10 volte finché non "riesce". Dopodiché, non voglio che l'attività venga ripetuta. Quindi in pratica ho bisogno di interrompere l'esecuzione dell'attività pianificata quando voglio che venga interrotta, ma senza chiudere ScheduledThreadPoolExecutor. Qualche idea su come lo farei?Come interrompere un'attività in ScheduledThreadPoolExecutor una volta che penso che sia completata

Ecco alcuni pseudo -

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

risposta

28

eseguire questo test, stampa 1 2 3 4 5 e si ferma

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

Perfetto grazie! Sapevo del programmato, ma stavo cercando di usare questo modo: t = executor.scheduleAtFixedRate (new MyTask(), 0, 1, TimeUnit.SECONDS); t.cancel (true); che non avrebbe mai funzionato per ovvi motivi. Annullare l'attività all'interno dell'implementazione dell'attività sembra giusto. – mystarrocks

+0

Grazie. Questo ha aiutato. È interessante notare che questo esempio non esce mai. Penso che sia necessario un arresto dell'esecutore – Kirby

+0

O piuttosto è necessario un 't.get()' e un arresto dell'esecutore all'interno di un blocco catch di CancellationException – Kirby

5

Bell 'cancellata al di fuori della discussione:

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

volte thread non poteva essere annullato, questo risolto solitamente via volatile boolean isCancelled;

+1

Bel esempio guardando questo da un po 'di tempo affrontando un sacco di problemi a causa di questo .... Grazie :) – Luffy

2

CountDownLatch è un approccio alternativo. Al termine del thread, chiamare countDown() sul latch. Il thread chiamante chiama latch.await() fino al completamento di tutti i thread. A quel punto chiama ExecutorService.shutdownNow() in modo che il thread principale non si trasformi in uno zombi.

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