2013-01-20 12 views
42

Ho uno ScheduledExecutorService che i tempi di un compito diverso pochi periodicamente con .scheduleAtFixedRate(Runnable, INIT_DELAY, ACTION_DELAY, TimeUnit.SECONDS);come rimuovere un'attività da ScheduledExecutorService?

mi hanno anche un diverso Runnable che sto usando con questo scheduler. il problema inizia quando voglio rimuovere una delle attività dallo scheduler.

c'è un modo per farlo?

sto facendo la cosa giusta utilizzando uno scheduler per compiti diversi? qual è il modo migliore per implementarlo?

risposta

63

semplicemente annullare il futuro restituito da scheduledAtFixedRate():

public static void main(String[] args) throws InterruptedException { 
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); 
    Runnable r = new Runnable() { 
     @Override 
     public void run() { 
      System.out.println("Hello"); 
     } 
    }; 
    ScheduledFuture<?> scheduledFuture = 
     scheduledExecutorService.scheduleAtFixedRate(r, 1L, 1L, TimeUnit.SECONDS); 
    Thread.sleep(5000L); 
    scheduledFuture.cancel(false); 
} 

Un'altra cosa da notare è che annulla non rimuove il compito di scheduler. Tutto ciò garantisce che il metodo isDone restituisca sempre true. Questo può portare a perdite di memoria se continui ad aggiungere tali compiti. Ad esempio, se si avvia un'attività in base a un'attività client o a un clic dell'interfaccia utente, ripetere n-volte e uscire. Se si fa clic su quel pulsante troppe volte, si potrebbe finire con un grande pool di thread che non possono essere raccolti come garbage data in cui lo scheduler ha ancora un riferimento.

È possibile utilizzare setRemoveOnCancelPolicy (true) nella classe ScheduledThreadPoolExecutor disponibile in Java 7 in poi. Per compatibilità con le versioni precedenti, il valore predefinito è impostato su falso.

+4

Nota per le persone che usano 'newSingleThreadScheduledExecutor()' in quanto non espone l'esecutore interno: Crea tu stesso un esecutore, imposta la proprietà, quindi avvolgilo con 'Executors.unconfigurableScheduledExecutorService()'. –

+1

Perché non riesco a riutilizzarlo? Perché è stato così difficile rimuovere le attività cancellate? – JohnyTex

+0

Per usare 'setRemoveOnCancelPolicy (true)', vedere la spiegazione delle varianti di istanziazione per 'ScheduledThreadPoolExecutor' qui: https://stackoverflow.com/a/36748183/3072570. – falvojr

0

Se l'istanza ScheduledExecutorService estende ThreadPoolExecutor (ad es ScheduledThreadPoolExecutor), è possibile utilizzare remove(Runnable) (ma si veda la nota nella sua javadoc: "E 'potrebbe non riuscire a rimuovere le attività che sono state convertite in altre forme, prima di essere immessi sul coda interna. ") o purge().

+0

grazie per la risposta, al momento questo metodo non esisteva in 'Executor' – thepoosh