Timer & TimerTask versus Thread + sleep en Java


Encontré preguntas similares aquí pero no hubo respuestas para mi satisfacción. Así que reformulando la pregunta de nuevo -

Tengo una tarea que debe hacerse de forma periódica (por ejemplo, intervalos de 1 minuto). ¿Cuál es la ventaja de usar Timertask & Timer para hacer esto en lugar de crear un nuevo hilo que tenga un bucle infinito con sleep?

Fragmento de código usando timertask -

TimerTask uploadCheckerTimerTask = new TimerTask(){

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

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

Fragmento de código usando Thread y sleep -

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

Realmente no tengo que preocuparme si perder ciertos ciclos si la ejecución de la lógica toma más tiempo que el intervalo.

Por favor, comente esto..

Actualización:
Recientemente encontré otra diferencia entre usar Temporizador versus Hilo.dormir(). Supongamos que la hora actual del sistema es 11: 00AM. Si revertimos la hora del sistema a las 10:00 AM por alguna razón, El Temporizador DEJARÁ de ejecutar la tarea hasta que haya alcanzado las 11:00 AM, mientras que Thread.el método sleep () continuaría ejecutando la tarea sin obstáculos. Esto puede ser un importante tomador de decisiones para decidir qué usar entre estos dos.

Author: Keshav, 2009-09-21

7 answers

La ventaja de TimerTask es que expresa tu intención mucho mejor (es decir, legibilidad del código), y ya tiene implementada la función cancel ().

Tenga en cuenta que se puede escribir en una forma más corta, así como su propio ejemplo:

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);
 64
Author: Zed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-04 19:15:40

Timer/TimerTask también tiene en cuenta el tiempo de ejecución de su tarea, por lo que será un poco más preciso. Y se ocupa mejor de los problemas de subprocesos múltiples (como evitar bloqueos, etc.).). Y, por supuesto, por lo general es mejor utilizar código estándar bien probado en lugar de alguna solución casera.

 12
Author: MartinStettner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-21 08:02:35

No se por qué, pero un programa que estaba escribiendo estaba usando Temporizadores y su tamaño de pila estaba aumentando constantemente, una vez que lo cambié a Thread/sleep problem solved.

 4
Author: Qandeel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-03 03:40:08

Hay un argumento crucial en contra de administrar esta tarea usando subprocesos Java y el método sleep. Estás usando while(true) para permanecer indefinidamente en el bucle e hibernar el hilo poniéndolo en reposo. Qué pasa si NewUploadServer.getInstance().checkAndUploadFiles(); ocupa algunos recursos sincronizados. Otros hilos no podrán acceder a estos recursos, puede ocurrir inanición que puede ralentizar toda su aplicación. Este tipo de errores son difíciles de diagnosticar y es una buena idea prevenir su existencia.

El otro enfoque activa la ejecución del código que te importa, es decir, NewUploadServer.getInstance().checkAndUploadFiles(); llamando al método run() de tu TimerTask mientras dejas que otros subprocesos usen los recursos mientras tanto.

 3
Author: Boris Pavlović,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-08 08:17:15

Si el hilo obtiene excepción y se mata, eso es un problema. Pero TimerTask se encargará de ello. Se ejecutará independientemente del fallo en la ejecución anterior.

 3
Author: Stack Popper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-06 19:45:48

Creo que entiendo su problema, estoy viendo algo muy similar. Tengo temporizadores que son recurrentes, algunos cada 30 minutos y algunos cada par de días. Por lo que leí y los comentarios que veo, parece que la recolección de basura nunca se ejecutará porque todas las tareas nunca están completas. Yo pensaría que la recolección de basura se ejecutaría cuando un temporizador está en reposo, pero no lo estoy viendo y de acuerdo con la documentación no lo hace.

Creo que generar nuevos hilos completa y permitir la recolección de basura.

Alguien por favor demuéstrame que me equivoco, reescribir lo que heredé va a ser un dolor.

 1
Author: Ken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-20 03:24:48

De la Timer documentación :

Java 5.0 introdujo java.útil.paquete concurrente y uno de los utilidades de concurrencia allí es el ScheduledThreadPoolExecutor que es un grupo de subprocesos para ejecutar tareas repetidamente a un ritmo determinado o retraso. Es efectivamente un reemplazo más versátil para el Combinación de temporizador / TimerTask, ya que permite múltiples hilos de servicio, acepta varias unidades de tiempo y no requiere subclase TimerTask (simplemente implementar Runnable). La Configuración De ScheduledThreadPoolExecutor con un hilo lo hace equivalente al Temporizador.

Así que Prefiere ScheduledThreadExecutor en lugar de Timer:

  • Timer utiliza un único hilo de fondo que se utiliza para ejecutar todas las tareas del temporizador, secuencialmente. Por lo tanto, las tareas deben completarse rápidamente, de lo contrario, retrasará la ejecución de las tareas posteriores. Pero en el caso de ScheduledThreadPoolExecutor podemos configurar cualquier número de hilos y también podemos tener control total proporcionando ThreadFactory.
  • Timer puede ser sensible al reloj del sistema, ya que hace uso del método Object.wait(long). Pero ScheduledThreadPoolExecutor no lo es.
  • Las excepciones en tiempo de ejecución lanzadas en TimerTask matarán ese hilo en particular, lo que hará que el temporizador esté muerto cuando podamos manejar eso en ScheduledThreadPoolExecutor para que las otras tareas no se vean afectadas.
  • Timer proporciona el método cancel para terminar el temporizador y descartar cualquier tarea programada, sin embargo, no interfiere con la tarea actualmente en ejecución y la deja terminar. Pero si el temporizador es ejecutándose como subproceso daemon, ya sea que lo cancelemos o no, terminará tan pronto como todos los subprocesos de usuario terminen de ejecutarse.

Temporizador vs Hilo.dormir

Temporizador hace uso de Object.wait y es diferente de Thread.sleep

  1. Un hilo en espera (wait) puede ser notificado (usando notify) por otro hilo, pero uno en espera no puede ser, solo puede ser interrumpido.
  2. Una espera (y notificación) debe ocurrir en un bloque sincronizado en el objeto monitor mientras que el sueño no.
  3. Mientras que dormir no libera el bloqueo, esperar liberará el bloqueo para el objeto al que se llama wait.
 0
Author: i_am_zero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-13 04:01:36