2012-09-24 3 views
9

Ho un compito che mi richiede di pianificare le attività e rimuoverle quando si verifica un determinato evento. Sto usando un ScheduledThreadPoolExecutor per pianificare le attività, è piuttosto semplice. Ma ho trovato due modi per cancellare gli elementi in sospeso, entrambi sembrano un po 'strani.Come cancellare gli elementi in sospeso da ScheduledThreadPoolExecutor?

Sono curioso di sapere se qualcuno di questi è di qualità di produzione. Se nessuno di loro, allora cosa suggerisci?

Ecco uno scheletro di quello che faccio:

private final ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1); 

public void doStuff() { 
    //... 
    scheduler.schedule(new Runnable() {/*...*/}, 10, TimeUnit.MILISECONDS) 
} 

public void actOnEvent() { 
    cancelPendingItems(); 
    doMoreStuff(); 
} 

public void cancelPendnigItems() { 
    // TODO implement me 
} 

Questo è candidata 1:

public void cancelPendingItems() { 
    scheduler.getQueue().clear(); 
} 

Questo è candidato 2:

public void cancelPendingItems() { 
    for (Runnable task : scheduler.getQueue()) { 
     scheduler.remove(task); 
    } 
} 

Entrambi sembrano un trucco per me perché dipendono dalla proprietà ScheduledThreadPoolExecutor.queue che non è specificata nell'interfaccia di ScheduledExecutor . Sono un po 'preoccupato che potrei violare un invariante di ScheduledThreadPoolExecutor e lo rileverò troppo tardi.

Quindi, questi snippet faranno ciò che voglio che facciano? Ci sono modi migliori/più puliti per farlo?

risposta

4

Vorrei utilizzare un List<Future>:

private final List<Future> futures = ... 

public void doStuff() { 
    futures.add(scheduler.schedule(new Runnable() {/*...*/}, 10, 
     TimeUnit.MILISECONDS)); 
} 

public void cancelPendingItems() { 
    for(Future future: futures) 
     future.cancel(true); 
    futures.clear(); 
} 
+1

Grazie! Fortunatamente, si adatta al mio problema reale perché non ci sono troppe attività possibili, quindi questa pulizia sarà ragionevolmente veloce. Quale è importante per la nostra applicazione con risorse limitate. –

2

Future.cancel(boolean mayInterruptIfRunning)

tentativi di annullare l'esecuzione di questa operazione. Questo tentativo fallirà se l'attività è già stata completata, già annullata o non può essere annullata per altri motivi. Se l'operazione è andata a buon fine e questa attività non è iniziata quando si chiama cancel, questa attività non dovrebbe mai essere eseguita. Se l'attività è già stata avviata, il parametro mayInterruptIfRunning determina se il thread che esegue questa attività deve essere interrotto nel tentativo di interrompere l'attività.

Oppure si può anche utilizzare ScheduledThreadPoolExecutor#shutdownNow

I tentativi di fermare tutte le attività che eseguono attivamente, arresta il trattamento dei task in attesa, e restituisce un elenco delle attività che sono stati in attesa di esecuzione.

Non ci sono garanzie al di là dei tentativi best-effort di interrompere l'elaborazione delle attività di esecuzione attiva. Questa implementazione annulla le attività tramite Thread.interrupt(), quindi qualsiasi attività che non riesce a rispondere agli interrupt potrebbe non terminare mai.

Quindi è necessario gestire InterruptedException per consentire l'uscita sicura dei thread che vengono annullati.