Java Timer vs ExecutorService?

Ho il codice in cui pianifico un’attività utilizzando java.util.timer . Stavo guardando in giro e ho visto ExecutorService può fare lo stesso. Quindi, questa domanda qui, hai usato Timer ed ExecutorService per pianificare i compiti, qual è il vantaggio di uno che usa su un altro?

Volevo anche verificare se qualcuno avesse usato la class Timer e si fosse imbattuto in qualsiasi problema risolto da ExecutorService .

Secondo Java Concurrency in Practice :

  • Timer può essere sensibile alle modifiche dell’orologio di sistema, ScheduledThreadPoolExecutor no.
  • Timer ha un solo thread di esecuzione, quindi un’attività a esecuzione prolungata può ritardare altre attività. ScheduledThreadPoolExecutor può essere configurato con qualsiasi numero di thread. Inoltre, hai il pieno controllo sui thread creati, se lo desideri (fornendo ThreadFactory ).
  • Le eccezioni di runtime lanciate in TimerTask quel thread, rendendo quindi Timer morto 🙁 … cioè le attività pianificate non verranno più eseguite. ScheduledThreadExecutor non afterExecute solo eccezioni di runtime, ma consente di gestirle se lo si desidera (ignorando il metodo afterExecute da ThreadPoolExecutor ). L’attività che ha ThreadPoolExecutor un’eccezione verrà annullata, ma altre attività continueranno a essere eseguite.

Se è ansible utilizzare ScheduledThreadExecutor anziché Timer , farlo.

Un’altra cosa … mentre ScheduledThreadExecutor non è disponibile nella libreria Java 1.4, esiste un backport di JSR 166 ( java.util.concurrent ) in Java 1.2, 1.3, 1.4 , che ha la class ScheduledThreadExecutor .

Se è disponibile, è difficile pensare a un motivo per non utilizzare il framework per esecutori Java 5. Calling:

 ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(); 

ti darà un servizio ScheduledExecutorService con funzionalità simili a Timer (cioè sarà a thread singolo) ma il cui accesso potrebbe essere leggermente più scalabile (sotto la cappa, utilizza strutture concorrenti piuttosto che la sincronizzazione completa come con la class Timer ). L’utilizzo di ScheduledExecutorService offre anche vantaggi quali:

  • È ansible personalizzarlo se necessario (consultare newScheduledThreadPoolExecutor() o la class ScheduledThreadPoolExecutor )
  • Le esecuzioni “una tantum” possono restituire risultati

Circa le uniche ragioni per attenersi a Timer posso pensare sono:

  • È disponibile pre-Java 5
  • Una class simile è fornita in J2ME, che potrebbe semplificare il porting della tua applicazione (ma in questo caso non sarebbe molto difficile aggiungere un livello comune di astrazione)

ExecutorService è più recente e più generale. Un timer è solo un thread che esegue periodicamente roba che hai programmato per esso.

Un ExecutorService può essere un pool di thread, o anche distribuito su altri sistemi in un cluster e fare cose come l’esecuzione in batch una tantum, ecc …

Basta guardare ciò che ognuno offre per decidere.

Ecco alcune buone pratiche sull’utilizzo di Timer:

http://tech.puredanger.com/2008/09/22/timer-rules/

In generale, userei Timer per cose veloci e sporche ed Executor per un uso più robusto.

La ragione per cui a volte preferisco il Timer su Executors.newSingleThreadScheduledExecutor () è che ottengo un codice molto più pulito quando ho bisogno che il timer esegua su thread daemon.

confrontare

 private final ThreadFactory threadFactory = new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setDaemon(true); return t; } }; private final ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(threadFactory); 

con

 private final Timer timer = new Timer(true); 

Lo faccio quando non ho bisogno della robustezza di un servizio executors.

Dalla pagina di documentazione di Oracle su ScheduledThreadPoolExecutor

Un ThreadPoolExecutor che può inoltre programmare i comandi da eseguire dopo un determinato ritardo o da eseguire periodicamente. Questa class è preferibile a Timer quando sono necessari più thread di lavoro o quando sono richieste la flessibilità o le funzionalità aggiuntive di ThreadPoolExecutor (che questa class estende).

ExecutorService/ThreadPoolExecutor o ScheduledThreadPoolExecutor è una scelta ovvia quando si hanno più thread di lavoro.

Professionisti di ExecutorService over Timer

  1. Timer non può sfruttare i core CPU disponibili a differenza di ExecutorService particolare con più attività che utilizzano i sapori di ExecutorService come ForkJoinPool
  2. ExecutorService fornisce API collaborative se è necessario il coordinamento tra più attività. Supponete di dover inviare N numero di compiti di lavoro e attendere il completamento di tutti loro. Puoi facilmente ottenerlo con invokeAll API. Se si desidera ottenere lo stesso con più attività del Timer , non sarebbe semplice.
  3. ThreadPoolExecutor fornisce API migliori per la gestione del ciclo di vita dei thread.

    I pool di thread risolvono due problemi diversi: in genere forniscono prestazioni migliori durante l’esecuzione di un numero elevato di attività asincrone, a causa di un sovraccarico di chiamata per attività ridotto e forniscono un mezzo per limitare e gestire le risorse, inclusi i thread, consumati durante l’esecuzione di una raccolta di compiti. Ogni ThreadPoolExecutor mantiene anche alcune statistiche di base, come il numero di attività completate

    Pochi vantaggi:

    un. È ansible creare / gestire / controllare il ciclo di vita dei thread e ottimizzare i costi generali di creazione dei thread

    b. È ansible controllare l’elaborazione delle attività (Work Stealing, ForkJoinPool, invokeAll) ecc.

    c. È ansible monitorare lo stato di avanzamento e la salute dei thread

    d. Fornisce un migliore meccanismo di gestione delle eccezioni