Domanda

Ho un codice in cui pianifico un'attività usando java.util.timer . Mi guardavo intorno e ho visto ExecutorService fare lo stesso. Quindi, questa domanda qui, hai usato Timer e ExecutorService per pianificare le attività, quali sono i vantaggi di uno che ne utilizza un altro?

Voleva anche verificare se qualcuno avesse usato la classe Timer e si fosse imbattuto in qualsiasi problema risolto per loro da ExecutorService .

È stato utile?

Soluzione

Secondo Java Concurrency in Practice :

  • Timer può essere sensibile alle modifiche dell'orologio di sistema, ScheduledThreadPoolExecutor non lo è.
  • Timer ha solo un thread di esecuzione, quindi un'attività di lunga durata 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 uccidono quel thread, rendendo Timer morto :-( ... cioè le attività pianificate non verranno più eseguite. ScheduledThreadExecutor non solo rileva le eccezioni di runtime, ma consente di gestirle se lo si desidera (sostituendo il metodo afterExecute da ThreadPoolExecutor ). L'attività che ha generato l'eccezione verrà annullata, ma altre attività continueranno a essere eseguite.

Se puoi usare ScheduledThreadExecutor invece di Timer , fallo.

Un'altra cosa ... mentre ScheduledThreadExecutor non è disponibile nella libreria Java 1.4, c'è un Backport di JSR 166 ( java.util.concurrent ) su Java 1.2, 1.3, 1.4 , che ha la classe ScheduledThreadExecutor .

Altri suggerimenti

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

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

ti darà un ScheduledExecutorService con funzionalità simili a Timer (cioè sarà a thread singolo) ma il cui accesso potrebbe essere leggermente più scalabile (sotto il cofano, esso utilizza strutture simultanee anziché la sincronizzazione completa come con la classe Timer ). L'uso di un ScheduledExecutorService offre anche vantaggi come:

  • Puoi personalizzarlo se necessario (vedi la classe newScheduledThreadPoolExecutor () o ScheduledThreadPoolExecutor )
  • Le esecuzioni 'una tantum' possono restituire risultati

Circa gli unici motivi per attenermi a Timer che posso pensare sono:

  • È disponibile prima di Java 5
  • In J2ME viene fornita una classe simile, che potrebbe semplificare il porting dell'applicazione (ma in questo caso non sarebbe tremendamente difficile aggiungere un livello comune di astrazione)

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

Un ExecutorService può essere un pool di thread oppure può essere distribuito su altri sistemi in un cluster e fare cose come l'esecuzione in batch una tantum, ecc ...

Guarda cosa offre ciascuno di decidere.

Ecco alcune altre buone pratiche sull'uso del timer:

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

In generale, userei Timer per roba veloce e sporca ed Executor per un uso più robusto.

Il motivo per cui a volte preferisco Timer rispetto a Executors.newSingleThreadScheduledExecutor () è che ottengo un codice molto più pulito quando ho bisogno del timer per essere eseguito sui thread demone.

confronta

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 solidità di un servizio di esecuzione.

Dalla pagina della documentazione Oracle su ScheduledThreadPoolExecutor

  

Un ThreadPoolExecutor che può inoltre programmare l'esecuzione dei comandi dopo un determinato ritardo o l'esecuzione periodica. Questa classe è preferibile a Timer quando sono necessari più thread di lavoro o quando sono richieste la flessibilità o le capacità aggiuntive di ThreadPoolExecutor (che estende questa classe).

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

Pro di ExecutorService su Timer

  1. Timer non può sfruttare i core della CPU disponibili a differenza di ExecutorService , in particolare con più attività che utilizzano le varianti di ExecutorService come ForkJoinPool
  2. ExecutorService fornisce API collaborative se è necessario il coordinamento tra più attività. Supponiamo di dover inviare un numero N di attività di lavoro e attendere il completamento di tutte. Puoi facilmente raggiungerlo con invokeAll . Se si desidera ottenere lo stesso risultato con più attività Timer , non sarebbe semplice.
  3. ThreadPoolExecutor fornisce una migliore API per la gestione del ciclo di vita di Thread.

      

    I pool di thread risolvono due diversi problemi: di solito forniscono prestazioni migliorate quando si eseguono un gran numero di attività asincrone, a causa del ridotto sovraccarico di invocazione per attività e forniscono un mezzo per delimitare e gestire le risorse, inclusi i thread, consumati durante l'esecuzione una raccolta di compiti. Ogni ThreadPoolExecutor mantiene anche alcune statistiche di base, come il numero di attività completate

    Pochi vantaggi:

    a. Puoi creare / gestire / controllare il ciclo di vita di Thread & amp; ottimizzare le spese generali per la creazione di thread

    b. Puoi controllare l'elaborazione delle attività (Gestione furto, ForkJoinPool, invokeAll) ecc.

    c. Puoi monitorare l'avanzamento e lo stato dei thread

    d. Fornisce un migliore meccanismo di gestione delle eccezioni

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top