Timer e TimerTask contro Thread + sleep in Java


102

Ho trovato domande simili poste qui ma non c'erano risposte di mia soddisfazione. Quindi riformulare di nuovo la domanda-

Ho un compito che deve essere svolto periodicamente (ad esempio intervalli di 1 minuto). Qual è il vantaggio di utilizzare Timertask & Timer per fare questo rispetto alla creazione di un nuovo thread che ha un ciclo infinito con sleep?

Snippet di codice utilizzando timertask-

TimerTask uploadCheckerTimerTask = new TimerTask(){

 public void run() {
  NewUploadServer.getInstance().checkAndUploadFiles();
 }
};

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);

Snippet di codice utilizzando Thread e sleep-

Thread t = new Thread(){
 public void run() {
  while(true) {
   NewUploadServer.getInstance().checkAndUploadFiles();
   Thread.sleep(60 * 1000);
  }
 }
};
t.start();

Non devo davvero preoccuparmi se perdo determinati cicli se l'esecuzione della logica richiede più dell'intervallo.

Si prega di commentare questo ..

Aggiornamento: di
recente ho trovato un'altra differenza tra l'utilizzo di Timer e Thread.sleep (). Supponiamo che l'ora di sistema corrente sia le 11:00. Se per qualche motivo eseguiamo il rollback dell'ora di sistema alle 10:00 AM, il timer INTERROMPERÀ l'esecuzione dell'attività finché non avrà raggiunto le 11:00, mentre il metodo Thread.sleep () continuerà a eseguire l'attività senza ostacoli. Questo può essere un importante decisore nel decidere cosa usare tra questi due.


21
Mozione d'ordine: Timer e TimerTask sono obsoleti e sono stati effettivamente sostituiti da ExecutorService, sebbene il tuo punto sia ancora valido.
skaffman

Grazie per il suggerimento, ho deciso di utilizzare ExecutorService :)
Keshav

Grazie a tutti per le risposte, sicuramente mi hanno dato più comprensione!
Keshav

6
Il timer non è obsoleto ed è preferito quando è necessario un solo thread. ( java.sun.com/javase/6/docs/api/java/util/Timer.html )
Justin

2
Timer e TimerTask sono ancora utili negli ambienti JME in cui ExecutorService non esiste (poiché basato su JME Java 1.3 ...).
ス ー パ ー フ ァ ミ コ ン

Risposte:


67

Il vantaggio di TimerTask è che esprime la tua intenzione molto meglio (cioè leggibilità del codice), e ha già implementato la funzione cancel ().

Nota che può essere scritto in una forma più breve così come il tuo esempio:

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);

se il timer è utilizzato per tutti i giorni, su 2 ore specifiche 21:00 e 9:00, ... come dare i valori? sul codice sopra ... @Zed?
gumuruh

12

Timer / TimerTask tiene anche conto del tempo di esecuzione del tuo compito, quindi sarà un po 'più preciso. E gestisce meglio i problemi di multithreading (come evitare deadlock, ecc.). E ovviamente di solito è meglio usare codice standard ben testato invece di qualche soluzione fatta in casa.


5

Non so perché, ma un programma che stavo scrivendo utilizzava i timer e la dimensione dell'heap aumentava costantemente, una volta che l'ho modificata in Thread / problema di sospensione risolto.


9
Il timer crea una coda di attività che viene continuamente aggiornata. Quando il timer è terminato, potrebbe non essere immediatamente sottoposto a Garbage Collection. Quindi la creazione di più timer aggiunge solo più oggetti all'heap. Thread.sleep () mette in pausa solo il thread, quindi l'overhead della memoria sarebbe estremamente basso.
Darryl Gerrow,

4

Se il thread riceve un'eccezione e viene ucciso, questo è un problema. Ma TimerTask se ne occuperà. Verrà eseguito indipendentemente dal guasto nell'esecuzione precedente.


4

Dalla Timer documentazione :

Java 5.0 ha introdotto il pacchetto java.util.concurrent e una delle utilità di concorrenza in esso è ScheduledThreadPoolExecutor che è un pool di thread per l'esecuzione ripetuta di attività a una determinata velocità o ritardo. È effettivamente un sostituto più versatile per la combinazione Timer / TimerTask, poiché consente più thread di servizio, accetta varie unità di tempo e non richiede la sottoclasse TimerTask (implementa solo Runnable). La configurazione di ScheduledThreadPoolExecutor con un thread lo rende equivalente a Timer.

Quindi preferisci ScheduledThreadExecutorinvece di Timer:

  • Timerutilizza un singolo thread in background che viene utilizzato per eseguire tutte le attività del timer, in sequenza. Quindi le attività dovrebbero essere completate rapidamente, altrimenti ritarderà l'esecuzione delle attività successive. Ma in questo caso ScheduledThreadPoolExecutorpossiamo configurare un numero qualsiasi di thread e possiamo anche avere il pieno controllo fornendo ThreadFactory.
  • Timerpuò essere sensibile all'orologio di sistema poiché utilizza il Object.wait(long)metodo. Ma ScheduledThreadPoolExecutornon lo è.
  • Le eccezioni di runtime generate in TimerTask uccideranno quel particolare thread, rendendo così Timer morto dove possiamo gestirlo in ScheduledThreadPoolExecutormodo che le altre attività non siano influenzate.
  • Timerfornisce un cancelmetodo per terminare il timer e scartare qualsiasi attività pianificata, tuttavia non interferisce con l'attività attualmente in esecuzione e lascia che finisca. Ma se il timer è in esecuzione come thread daemon, indipendentemente dal fatto che lo cancelliamo o meno, terminerà non appena tutti i thread dell'utente avranno terminato l'esecuzione.

Timer vs Thread.sleep

Timer utilizza Object.waited è diverso daThread.sleep

  1. Un waitthread in attesa ( ) può essere notificato (usando notify) da un altro thread ma uno inattivo non può esserlo, può solo essere interrotto.
  2. Un'attesa (e una notifica) deve avvenire in un blocco sincronizzato sull'oggetto monitor mentre il sonno no.
  3. Mentre lo sleep non rilascia il blocco, l'attesa rilascerà il blocco per l'oggetto wait è chiamato.

informazioni molto utili, Inoltre, l'utilizzo di Thread.sleep in un ciclo infinito può causare un elevato utilizzo della CPU con tempi di ritardo ridotti.
Amir Fo

3

C'è un argomento cruciale contro la gestione di questa attività utilizzando thread e sleepmetodi Java . Stai usando while(true)per rimanere indefinitamente nel ciclo e ibernare il thread mettendolo a dormire. E se NewUploadServer.getInstance().checkAndUploadFiles();occupasse alcune risorse sincronizzate. Altri thread non saranno in grado di accedere a queste risorse, potrebbe verificarsi la fame che può rallentare l'intera applicazione. Questi tipi di errori sono difficili da diagnosticare ed è una buona idea prevenirne l'esistenza.

L'altro approccio innesca l'esecuzione del codice che ti interessa, cioè NewUploadServer.getInstance().checkAndUploadFiles();chiamando il run()metodo del tuo TimerTasklasciando che nel frattempo altri thread utilizzino le risorse.


16
Non capisco questo argomento. Entrambe le scelte avviano lo stesso metodo da un thread, entrambe le scelte dormono in un thread mentre attendono di essere eseguite. Non ci saranno differenze di fame tra le due scelte.
sabato 9

2

Penso di aver capito il tuo problema, vedo qualcosa di molto simile. Ho timer ricorrenti, alcuni ogni 30 minuti e alcuni ogni due giorni. Da quello che ho letto e dai commenti che vedo, sembra che la garbage collection non verrà mai eseguita perché tutte le attività non sono mai complete. Penserei che la garbage collection venga eseguita quando un timer è in sospensione, ma non lo vedo e secondo la documentazione non lo fa.

Penso che la generazione di nuovi thread completi e consenta la raccolta dei rifiuti.

Qualcuno, per favore, dimostri che ho torto, riscrivere ciò che ho ereditato sarà un dolore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.