1. Descripción general
Implementación de la función de ejecutar tareas regularmente en Java, principalmente utilizando dos clases, temporizador y clases de TimeTask. El temporizador se utiliza para ejecutar las tareas especificadas en un hilo de fondo de acuerdo con el plan especificado.
TimeTkask es una clase abstracta, y su subclase representa una tarea que puede ser planificada por el temporizador. El código específico que se ejecutará se escribe en el método Ejecutar que TimeTask debe implementarse.
2. Echemos un vistazo al ejemplo más simple
Vamos a explicarlo a través del código
import java.text.simpledateFormat; import java.util.date; import java.util.timer; import java.util.timerTask; public class TimerDemo {public static string getCurrentTime () {fecha date = nueva fecha (); SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (fecha); } public static void main (string [] args) lanza interruptedException {System.out.println ("Start principal:"+getCurrentTime ()); startTimer (); Thread.sleep (1000*5); // dormir durante 5 segundos System.out.println ("End Main:"+getCurrentTime ()); } public static void startTimer () {timeTask tarea = new TimeTk () {@Override public void run () {System.out.println ("Task Run:"+getCurrentTime ()); }}; Temporizador temporizador = new Timer (); Timer.schedule (tarea, 0); }}Para facilitar la información de observación mediante la impresión, agregamos cierta información de impresión al método principal y llamamos Subh. Sleep para hacer que el hilo principal duerma. Además, se agrega un método GetCurrentTime a la clase para obtener la fecha actual.
En el código anterior, en el método StartTimer, se crea un objeto TimeTask (la tarea a ejecutar por el temporizador) y se crea un objeto de temporizador, y se llama al método de programación de la clase de temporizador. La clase de temporizador tiene múltiples métodos de programación con diferentes parámetros. Lo que se usa aquí es:
Horario de vacío público (tarea de TimeTask, retraso largo)
El significado de este método es ejecutar la tarea de la tarea después de que el temporizador retrasará el tiempo (milisegundos). Si el retraso es negativo o 0, la tarea se realizará de inmediato. Y es una tarea de ejecución única, y la tarea no se repetirá (o programada) posteriormente.
Para la clase de temporizador, también se proporciona un método con la misma función, de la siguiente manera:
Horario de vacío público (tarea de TimeTask, hora de fecha)
La diferencia entre este método y el método anterior es que el método anterior especifica que la ejecución se retrasa por un período de tiempo, y este método especifica que la ejecución se realiza en un punto específico en el tiempo. Tenga en cuenta que si la hora actual del sistema ha excedido el tiempo especificado por el tiempo del parámetro, la tarea se ejecutará de inmediato.
Al ejecutar el código anterior, descubrimos que el programa imprime inmediatamente dos información similar a la siguiente:
Inicio principal: 2016-01-13 22:23:18
Tarea Ejecutar: 2016-01-13 22:23:18
Debido a que el valor del parámetro de retraso que pasamos al método de programación aquí es 0, la tarea se ejecutará inmediatamente, por lo que el tiempo para imprimir las dos declaraciones es el mismo, que es lo que debería ser. Puede cambiar el valor de retraso entrante por sí mismo para ver los cambios en la información de salida. Después de unos 5 segundos (es decir, tiempo de sueño), seguí imprimiendo 1 mensaje:
Fin principal: 2016-01-13 22:23:23
El tiempo para la información de impresión es 5 segundos de la declaración anterior, lo cual es consistente con la configuración del sueño, lo que también es muy razonable.
Pero encontraremos un fenómeno muy interesante, y encontraremos que el proceso no saldrá. En este momento, el hilo principal principal ha terminado. Esto significa que después de que el temporizador complete la tarea, incluso si no hay tareas esperando ser ejecutadas más tarde, el hilo de fondo creado en el temporizador no saldrá de inmediato. Revisé la documentación relevante de Java Doc y expliqué que el hilo del temporizador no saldrá activamente y necesita esperar la recolección de basura, pero la recolección de basura de Java no puede ser controlada por el código en sí, pero está controlada por la máquina virtual.
Después de la investigación, se descubrió que al crear un objeto de temporizador y ejecutar el temporizador de temporizador = new Timer (); Declaración, se creará el hilo del temporizador. En otras palabras, incluso si el código anterior no tiene el temporizador.schedule (tarea, 0); Declaración, el programa no saldrá. Siento que esto es bastante irrazonable. Estudié el código fuente de la clase de temporizador nuevamente y descubrí que también tiene un constructor con parámetros booleanos:
Temporizador público (booleano isdaemon)
Como puede ver en el nombre del parámetro, si el valor del parámetro es verdadero, el hilo del temporizador creado por el temporizador es el hilo de demonio. El significado de un hilo de demonio es que cuando todos los roscas de los trabajadores en la salida del proceso Java, el hilo de demonio saldrá automáticamente.
En este momento, solo necesitamos cambiar el código para crear el objeto de temporizador en el ejemplo anterior a: Timer Timer = New Timer (True);
Después de encontrar que el programa se ejecuta, el programa saldrá después del hilo principal (el hilo principal no es un hilo de demonio, sino un hilo de trabajador), lo que significa que el hilo del temporizador también sale, lo que significa que después de agregar el parámetro verdadero, el hilo de demonio creado es el hilo de demonio.
Pero el problema es que en escenarios de aplicación real, hay muchos hilos de trabajadores en ejecución y el programa no saldrá de manera casual. Entonces, ¿qué pasa si quieres que el temporizador salga o cierre de inmediato? Presentaremos esto a continuación.
3. Salida del temporizador
La clase de temporizador proporciona un método de cancelación para cancelar el temporizador. Llamar al método de cancelación terminará este temporizador y descartará todas las tareas programadas actualmente. Esto no interfiere con la tarea de ejecución actualmente (si existe). Una vez que se termina el temporizador, su hilo de ejecución también terminará y no se pueden programar más tareas de acuerdo con él.
Tenga en cuenta que al llamar a este método dentro del método Ejecutar de la tarea del temporizador llamada este temporizador, puede asegurarse absolutamente de que la tarea ejecutada sea la última tarea ejecutada por este temporizador. Este método se puede llamar repetidamente; Sin embargo, las segundas y posteriores llamadas no son válidas.
Veamos otro código de ejemplo:
import java.text.simpledateFormat; import java.util.date; import java.util.timer; import java.util.timerTask; public class TimerDemo {public static string getCurrentTime () {fecha date = nueva fecha (); SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (fecha); } public static void main (string [] args) lanza interruptedException {System.out.println ("Start principal:"+getCurrentTime ()); Temporizador temporizador = startTimer (); Thread.sleep (1000*5); // dormir durante 5 segundos System.out.println ("End Main:"+getCurrentTime ()); Timer.cancel (); } public static timer startTimer () {TimeTask Task = new TimeTk () {@Override public void run () {System.out.println ("Task Run:"+getCurrentTime ()); }}; Temporizador temporizador = new Timer (); Timer.schedule (tarea, 0); temporizador de retorno; }} Ejecutar el programa es exactamente el mismo que la salida del ejemplo anterior. La diferencia es que cuando termina el método principal. El proceso saldrá activamente, lo que significa que el hilo del temporizador se ha cerrado.
Porque llamamos al método de cancelación en el método principal. Tenga en cuenta que si no está llamando al método Cancelar en el método Ejecutar de TimeTask, asegúrese de que la tarea que desea ejecutar ha comenzado o completado, de lo contrario si la tarea no ha comenzado a ejecutarse. Simplemente llame a Cancelar y todas las tareas no se ejecutarán. Por ejemplo, el código anterior,
Por ejemplo, en el código anterior, si no llamamos al método de cancelar en el método principal, pero agregue el temporizador.schedule (tarea, 0); instrucción en el método StartTimer y agregue el temporizador.cancel (); Declaración Después de ejecutar, encontrará que la tarea del temporizador no se ejecutará, porque se cancelará antes de que se complete la ejecución.
4. Ejecutar tareas regularmente
En el ejemplo anterior, estamos presentando una tarea única, es decir, ha llegado el tiempo del temporizador. Después de ejecutar la tarea, no se repetirá más adelante. En las aplicaciones reales, hay muchos escenarios que requieren la misma tarea que se ejecuta repetidamente regularmente. Hay dos situaciones: una es ejecutar tareas de vez en cuando, y la otra es realizar tareas en ciertos (o varios) puntos de tiempo todos los días (o semanalmente, mensualmente, etc.).
Primero veamos el primer caso, que es un ejemplo de ejecutar la misma tarea cada 10 segundos. El código es el siguiente:
import java.text.simpledateFormat; import java.util.date; import java.util.timer; import java.util.timerTask; public class TimerDemo {public static string getCurrentTime () {fecha date = nueva fecha (); SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (fecha); } public static void main (string [] args) lanza interruptedException {System.out.println ("Start principal:"+getCurrentTime ()); startTimer (); } public static void startTimer () {timeTask tarea = new TimeTk () {@Override public void run () {System.out.println ("Task Run:"+getCurrentTime ()); intente {Thread.sleep (1000*3); } catch (InterruptedException e) {E.PrintStackTrace (); }}}; Temporizador temporizador = new Timer (); Timer.schedule (tarea, 1000*5,1000*10); }} Ejecute el programa anterior y la información de salida es la siguiente (porque el temporizador no se detiene, y la tarea se repite, la salida se emitirá continuamente. Solo algunas de las salidas anteriores se copian aquí)
Inicio principal: 2016-01-14 08:41:14
Tarea Ejecución: 2016-01-14 08:41:19
Tarea Ejecución: 2016-01-14 08:41:29
Tarea Ejecutar: 2016-01-14 08:41:39
Tarea Ejecución: 2016-01-14 08:41:49
Tarea Ejecutar: 2016-01-14 08:42:00
Tarea Ejecución: 2016-01-14 08:42:10
Tarea Ejecución: 2016-01-14 08:42:20
Tarea Ejecutar: 2016-01-14 08:42:30
Tarea Ejecutar: 2016-01-14 08:42:40
En el código anterior, llamamos temporizador.schedule (tarea, 1000*5,1000*10); Esto significa que la tarea se retrasa en 5 segundos, y luego se repetirá cada 10 segundos. Observamos que el tiempo de impresión en la información de salida es el mismo que se esperaba. Además, se puede ver que el intervalo se calcula en función de la hora de inicio de la tarea, es decir, no es esperar otros 10 segundos después de que se complete la tarea.
La clase de temporizador tiene dos métodos para implementar tales funciones, como sigue:
Horario público nulo (tarea de tiempo de tiempo, retraso largo, período largo) Programa de vacío público (tarea de tiempo de tiempo, fecha en la primera vez, período largo)
El primer método que usamos anteriormente. La diferencia entre los dos métodos es el tiempo de la primera ejecución. El primer método se ejecuta después de un retraso especificado de un período de tiempo (en milisegundos); El segundo método se ejecuta en un punto de tiempo especificado.
En este momento, consideramos el siguiente escenario. Si el tiempo de ejecución de una tarea excede la próxima hora de espera, ¿qué pasará? Veamos a través del código:
import java.text.simpledateFormat; import java.util.date; import java.util.timer; import java.util.timerTask; public class TimerDemo {public static string getCurrentTime () {fecha date = nueva fecha (); SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (fecha); } public static void main (string [] args) lanza interruptedException {System.out.println ("Start principal:"+getCurrentTime ()); startTimer (); } public static void startTimer () {timeTask tarea = new TimeTk () {@Override public void run () {System.out.println ("Task Begin:"+getCurrentTime ()); intente {Thread.sleep (1000*10); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("Task End:"+getCurrentTime ()); }}; Temporizador temporizador = new Timer (); Timer.schedule (tarea, 1000*5,1000*5); }} En comparación con el código anterior, solo cambiamos 2 códigos y modificamos la impresión. Una es cambiar el sueño en el método Ejecutar a 10 segundos, y el otro es cambiar el ciclo de ejecución de la tarea a 5 segundos. En otras palabras, el tiempo de ejecución de la tarea excede el intervalo entre la ejecución repetida de la tarea. Ejecute el programa, la salida anterior es la siguiente:
Inicio principal: 2016-01-14 09:03:51
Tarea Begin: 2016-01-14 09:03:56
Fin de la tarea: 2016-01-14 09:04:06
Tarea Begin: 2016-01-14 09:04:06
Fin de la tarea: 2016-01-14 09:04:16
Tarea Begin: 2016-01-14 09:04:16
Fin de la tarea: 2016-01-14 09:04:26
Tarea Begin: 2016-01-14 09:04:26
Fin de la tarea: 2016-01-14 09:04:36
Tarea Begin: 2016-01-14 09:04:36
Fin de la tarea: 2016-01-14 09:04:46
Tarea Begin: 2016-01-14 09:04:46
Fin de la tarea: 2016-01-14 09:04:56
Se puede ver que después de ejecutar cada tarea, la siguiente tarea se ejecutará de inmediato. Debido a que el tiempo tardado desde el comienzo de la tarea hasta la finalización de la tarea ha excedido el intervalo entre la repetición de la tarea, la ejecución se repetirá.
5. Ejecutar tareas regularmente (repita el punto de tiempo fijo)
Implementemos dicha función, realice una tarea regularmente a la 1 a.m. todos los días, que tiene esta función en muchos sistemas, como completar tareas que requieren mucho tiempo y las tareas que requieren recursos, como la copia de seguridad de datos y las estadísticas de datos en esta tarea. El código es el siguiente:
import java.text.simpledateformat; import java.util.calendar; import java.util.date; import java.util.timer; import java.util.timerTask; clase pública TimerDemo {public static string getCurrentTime () {fecha de fecha = nueva fecha (); SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (fecha); } public static void main (string [] args) lanza interruptedException {System.out.println ("Start principal:" + getCurrentTime ()); startTimer (); } public static void startTimer () {timeTask tarea = new TimeTk () {@Override public void run () {System.out.println ("Task Begin:" + getCurrentTime ()); intente {Thread.sleep (1000 * 20); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("Task End:" + getCurrentTime ()); }}; Temporizador temporizador = new Timer (); timer.schedule (tarea, pledtime (), 1000 * 60 * 60 * 24); } fecha privada de fecha estática bidEdtime () {calendar calendar = calendar.getInstance (); calendar.set (calendar.hour_of_day, 1); calendario.set (calendario.minute, 0); calendar.set (calendario.segundo, 0); Fecha de fecha = calendario.gettime (); if (time.before (new Date ())) {// Si la hora actual es después de la 1 a.m., se necesita 1 día, de lo contrario, la tarea se ejecutará de inmediato. // Muchos sistemas a menudo necesitan ejecutar tareas inmediatamente cuando el sistema comienza, pero necesitan ejecutarlos a la 1 a.m. todos los días. ¿Qué tengo que hacer? // Es muy simple, solo ejecute la tarea por separado cuando el sistema inicializa la llamada (no se necesita un temporizador, es solo el código para ejecutar esa tarea) TIME = ADDDAY (TIEMPO, 1); } tiempo de retorno; } Fecha estática privada ADDDAY (fecha Fecha, INT Days) {Calendar StartDt = calendar.getInstance (); startdt.settime (fecha); startdt.add (calendar.day_of_month, días); return startdt.gettime (); }}Debido a que se ejecuta con 24 horas de diferencia, es imposible esperar la observación de la salida.
6. Resumen
Este artículo presenta el mecanismo de cómo realizar tareas cronometradas utilizando la clase de temporizador Java. Se puede ver que todavía hay muchas formas de prestar atención. En los ejemplos introducidos en este artículo, cada temporizador solo corresponde a una tarea.
El contenido introducido en este artículo puede cumplir con la mayoría de los escenarios de aplicaciones, pero ¿todavía hay algunos problemas, como incluir múltiples tareas para un temporizador? ¿Puedo agregar tareas nuevamente después de cancelar el temporizador? ¿Qué otros métodos están disponibles en la clase de temporizador? Estas preguntas se introducirán en la siguiente publicación de blog.
Enlace original: http://www.cnblogs.com/51kata/p/5128745.html
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.