Si necesitamos ejecutar algunas tareas de tiempo simples durante nuestro proceso de programación, no necesitamos hacer un control complejo. Podemos considerar usar tareas de tiempo de temporizador en JDK para lograrlo. El siguiente LZ analiza el temporizador de temporizador Java en función de su principio, ejemplo y defecto del temporizador.
1. Introducción
En Java, las clases de temporizador y TimeTask deben completar una tarea de tiempo completa. Así es como se definen en la API. Temporizador: una herramienta que lo usa para organizar tareas que los subprocesos realizan en los subprocesos de fondo más adelante. Las tareas se pueden ejecutar una vez, o se pueden ejecutar repetidamente. Tarea programada por TimeTask: Temperador como una tarea que se ejecuta o se repite. Podemos entender que el temporizador es una herramienta de temporizador utilizada para planear ejecutar tareas especificadas en un hilo de fondo, y TimeTask una clase abstracta cuya subclase representa una tarea que el temporizador puede planificar.
Clase de temporizador <Br /> En el temporizador de la clase de herramientas, se proporcionan cuatro métodos de constructor. Cada constructor inicia un hilo de temporizador. Al mismo tiempo, la clase de temporizador puede garantizar que múltiples subprocesos puedan compartir un objeto de temporizador único sin sincronización externa, por lo que la clase de temporizador es segura. Sin embargo, dado que cada objeto de temporizador corresponde a un solo hilo de fondo, que se utiliza para ejecutar todas las tareas del temporizador en secuencia, en general, el tiempo dedicado a la ejecución de nuestra tarea de hilo debería ser muy corto. Sin embargo, debido a las circunstancias especiales, el tiempo de ejecución de una determinada tarea del temporizador es demasiado largo, por lo que "exclusivamente" el hilo de ejecución de tareas del temporizador, y todos los hilos posteriores deben esperar a que se ejecute, lo que retrasará la ejecución de tareas posteriores y hará estas tareas juntas. Analizaremos la situación específica más adelante.
Cuando el programa inicializa el temporizador, la tarea de tiempo se ejecutará de acuerdo con el tiempo que establecemos. El temporizador proporciona el método de programación, que tiene múltiples sobrecargas para adaptarse a diferentes situaciones, de la siguiente manera:
Programa (Tarea de TimeTask, fecha de fecha): Programe la ejecución de la tarea especificada en la hora especificada.
Programa (Tarea de TimeTask, fecha en la primera vez, período largo): Programe la tarea especificada para iniciar la ejecución de retraso fijo repetido en el momento especificado.
Programación (tarea de TimeTask, retraso largo): programa la tarea especificada que se ejecutará después del retraso especificado.
Programa (tarea de TimerTask, retraso largo, período largo): Programe la tarea especificada que se ejecutará repetidamente retrasada después del retraso especificado.
Al mismo tiempo, el método ScheduleAtFixedRate también está sobrecargado. El método ScheduleAtFixedRate es el mismo que el horario, pero su enfoque es diferente, y la diferencia se analiza más adelante.
ProgrameAtFixedRate (tarea de TimeTask, fecha en la primera vez, período largo): Programe la tarea especificada que se ejecutará repetidamente a una velocidad fija a un momento especificado.
ScheduleAtFixedRate (tarea de TimeTask, retraso largo, período largo): Programe la tarea especificada para iniciar la ejecución repetida de tasa fija después del retraso especificado.
TimerTask
La clase TimeTask es una clase abstracta organizada por el temporizador como una tarea que se ejecuta o se repite. Tiene un método de ejecución () de método abstracto, que se utiliza para realizar las operaciones que se realizarán mediante la tarea del temporizador correspondiente. Por lo tanto, cada clase de tarea específica debe heredar TimeTask y luego anular el método Run ().
Además, tiene dos métodos no abstractos:
Boolean Cancel (): cancele esta tarea de temporizador.
Long ProchuleDExecutionTime (): Devuelve el tiempo de ejecución programado de la ejecución real más reciente de esta tarea.
2. Ejemplos
2.1. Especifique el tiempo de retraso para ejecutar tareas de tiempo
clase pública TimeTest01 {temporizador de temporizador; public TimeTest01 (int Time) {Timer = new Timer (); Timer.schedule (nuevo TimeTkTest01 (), Tiempo * 1000); } public static void main (string [] args) {System.out.println ("Temporizador Begin ..."); nuevo TimeTest01 (3); }} clase pública TimeTaskTest01 extiende TimeTask {public void run () {System.out.println ("Time's Up!"); }} Resultados de ejecución:
Primera impresión: el temporizador comienza ...
Imprima en 3 segundos: ¡Time está arriba!
2.2. Ejecutar tareas de tiempo en el momento especificado
clase pública TimeTest02 {temporizador de temporizador; public TimeTest02 () {date hime = getTime (); System.out.println ("especificar tiempo de tiempo =" + tiempo); temporizador = new Timer (); Timer.schedule (nuevo TimeTkTest02 (), tiempo); } Public Date getTime () {calendar calendar = calendar.getInstance (); calendar.set (calendar.hour_of_day, 11); calendario.set (calendario. Minute, 39); calendario.set (calendario. Segundo, 00); Fecha de fecha = calendario.gettime (); tiempo de regreso; } public static void main (string [] args) {new TimeTest02 (); }} public class TimeTASTAt02 extiende TimeTask {@Override public void run () {System.out.println ("Ejecutar tareas de subprocesos en el momento especificado ..."); }} Cuando la hora llegue a las 11:39:00, la tarea del hilo se ejecutará, por supuesto, se ejecutará incluso si es mayor que ese momento. ! El resultado de la ejecución es:
Tiempo especificado = martes 10 de junio 11:39:00 CST 2014
Ejecutar tareas de subprocesos en el momento especificado ...
2.3. Después de retrasar el tiempo especificado, la tarea de tiempo se ejecutará en el tiempo de intervalo especificado.
clase pública TimeTest03 {temporizador de temporizador; public timertest03 () {Timer = new Timer (); Timer.schedule (nuevo TimeTkTest03 (), 1000, 2000); } public static void main (string [] args) {new TimeTest03 (); }} public class TimeTAntT03 extiende TimeTask {@Override public void run () {date date = new Date (this.scheduleDExecutionTime ()); System.out.println ("El tiempo para ejecutar este hilo es:" + fecha); }} Resultados de ejecución:
El tiempo para ejecutar este hilo es: martes 10 de junio 21:19:47 CST 2014
El tiempo para ejecutar este hilo es: martes 10 de junio 21:19:49 CST 2014
El tiempo para ejecutar este hilo es: martes 10 de junio 21:19:51 CST 2014
El tiempo para ejecutar este hilo es: martes 10 de junio 21:19:53 CST 2014
El tiempo para ejecutar este hilo es: martes 10 de junio 21:19:55 CST 2014
El tiempo para ejecutar este hilo es: martes 10 de junio 21:19:57 CST 2014
................
Para esta tarea de hilo, si no detenemos la tarea, continuará ejecutándose.
Para los tres ejemplos anteriores, LZ lo demostró brevemente, y no explicó el ejemplo del método ScheduleAtFixedRate. De hecho, ¡este método es el mismo que el método de programación!
2.4. Analizar el cronograma y la lista de programación
1), Anexo (tarea de TimerTask, fecha de fecha), cronograma (tarea de tiempo de tiempo, retraso largo)
Para ambos métodos, si el ProgramedExecutionTime especificado <= SystemCurrentTime, la tarea se ejecutará de inmediato. ProchuleDExecutionTime no cambiará debido a la ejecución excesiva de una tarea.
2) Programa (tarea de Timtertak, fecha en la primera vez, período largo), Anexo (tarea de tiempo de tiempo, retraso largo, período largo)
Estos dos métodos son un poco diferentes de los dos anteriores. Como se mencionó anteriormente, la tarea del temporizador se retrasará porque la tarea anterior se ejecuta durante mucho tiempo. En estos dos métodos, el tiempo programado de cada tarea ejecutada cambiará con el tiempo real de la tarea anterior, es decir, ProgramedExecutionTime (n+1) = realexCutionTime (n)+periódico. Es decir, si la enésima tarea causa este proceso de tiempo de ejecución debido a alguna situación, y finalmente SystemCurrentTime> = ProgramedExecutionTime (n+1), esta es la tarea N+1 y no se ejecutará debido al tiempo. Esperará a que la enésima tarea se ejecute antes de la ejecución, entonces esto inevitablemente conducirá a la implementación de ejecución N+2 ProgramedExeCutionTime Liberación y cambio, es decir, ProgramedExecutionTime (n+2) = ReaExeCutionTime (n+1)+PeriodTime. Por lo tanto, estos dos métodos prestan más atención a la estabilidad del tiempo de intervalo de almacenamiento.
3) ScheduleAtFixedRate (tarea de TimeTask, fecha en la primera vez, período largo), ScheduleAtFixedRate (tarea de TimeTask, retraso largo, período largo)
Como se mencionó anteriormente, el enfoque de los métodos ScheduleAtFixedRate y Schedule es diferente. El método de programación se centra en la estabilidad del tiempo de intervalo de ahorro, mientras que el método ScheduleAtFixedRate se centra más en mantener la estabilidad de la frecuencia de ejecución. ¿Por qué lo dices, las razones son las siguientes? En el método de programación, el retraso de la tarea anterior causará el retraso de la tarea de tiempo después de ella, mientras que el método ScheduleAtFixedRate no lo hará. Si el tiempo de ejecución de la enésima tarea es demasiado larga, SystemCurrentTime> = ProgramedExecutionTime (n+1), no habrá esperado que ejecute la tarea N+1 de inmediato. Por lo tanto, el método de cálculo del tiempo de ejecución del método ScheduleAtFixedRate es diferente del cronograma, pero ProchuleDExecutionTime (n) = FirstExecutetime +n*Periodtime, y el método de cálculo permanecerá sin cambios para siempre. Por lo tanto, ScheduleAtFixedRate se centra más en mantener estable la frecuencia de ejecución.
3. Defectos del temporizador
3.1. Defectos del temporizador
El temporizador del temporizador puede tiempo (ejecutar tareas en el momento especificado), retrasar (tareas de retraso en 5 segundos) y ejecutar tareas periódicamente (ejecutar tareas en 1 segundo), pero el temporizador tiene algunas deficiencias. En primer lugar, el soporte del temporizador para la programación se basa en el tiempo absoluto, no en el tiempo relativo, por lo que es muy sensible a los cambios en el tiempo del sistema. En segundo lugar, el hilo del temporizador no captará excepciones. Si TimeTask lanza la excepción sin control, hará que el hilo del temporizador termine. Al mismo tiempo, el temporizador no reanudará la ejecución del hilo, y creerá erróneamente que todo el hilo del temporizador se cancelará. Al mismo tiempo, TimeTkask, que ha sido programado para no ejecutarse aún, ya no se ejecutará y no se pueden programar nuevas tareas. Por lo tanto, si TimeTask lanza una excepción sin control, el temporizador producirá un comportamiento impredecible.
1) Defecto de retraso de tiempo de gestión del temporizador <Br /> El temporizador anterior solo creará una tarea de subproceso al ejecutar una tarea cronometrada. Si hay múltiples hilos, si uno de los subprocesos hace que el tiempo de ejecución de la tarea del hilo sea demasiado largo por alguna razón, y el intervalo entre las dos tareas excede el tiempo entre ellos, se producirán algunos defectos:
clase pública TimeTest04 {temporizador de temporizador privado; comienzo público largo; public TimeTest04 () {this.timer = new Timer (); start = System.CurrentTimemillis (); } public void timerOne () {timer.schedule (new TimerTask () {public void run () {System.out.println ("TimerOne Invoked, The Time:" + (System.CurrentTimEmillis () - inicio)); intente {Hread.slelee (4000); // Thread duerme 3000} CatchedExceptException E) {E. }}}}, 1000); } public void timertwo () {timer.schedule (new TimerTask () {public void run () {System.out.println ("TimerOne Invoced, The Time:" + (System.CurrentTimemillis () - Start));}}, 3000); } public static void main (string [] args) lanza la excepción {timeTest04 test = new TimeTest04 (); test.timerone (); test.timertwo (); }} Según nuestro pensamiento normal, TimertWo debe ejecutarse después de 3s, y el resultado debería ser:
Timerone invocado, la hora: 1001
Timerone invocado, la hora: 3001
Pero las cosas fueron en contra de mis expectativas. Timerone duerme (4000), duerme 4s y el temporizador está dentro del temporizador, lo que hace que el tiempo requerido para que TimeOne exceda el intervalo. El resultado:
Timerone invocado, la hora: 1000
Timerone invocado, la hora: 5000
2) El temporizador arroja defecto de excepción
Si TimeTask lanza una RuntimeException, el temporizador terminará todas las tareas. como sigue:
clase pública TimeTest04 {temporizador de temporizador privado; public TimeTest04 () {this.timer = new Timer (); } public void timerOne () {timer.schedule (new TimeTask () {public void run () {throw new runtimeException ();}}, 1000); } public void timertwo () {timer.schedule (new TimeTk () {public void run () {System.out.println ("¿Lo ejecutaré ??");}}, 1000); } public static void main (string [] args) {timeTest04 test = new TimeTest04 (); test.timerone (); test.timertwo (); }} Resultado de ejecución: Timerone lanza una excepción, lo que hace que la tarea de Timertwo termine.
Excepción en el hilo "Timer-0" java.lang.runtimeException en com.chenssy.timer.timertest04 $ 1.run (timertest04.java:25) en java.util.timerthread.mainloop (Timer.Java:555) en java.util.timerthread.run (temporal.Java:505)
Para los defectos del temporizador, podemos considerar ProchuledThreadPoolExecutor como un reemplazo. El temporizador se basa en el tiempo absoluto y es más sensible al tiempo del sistema, mientras que ProchuledThreadPoolExecutor se basa en el tiempo relativo; El temporizador es un solo hilo internamente, mientras que ProchuledThreadPoolExecutor es un grupo de hilos internamente, por lo que puede admitir la ejecución concurrente de múltiples tareas.
3.2. Reemplace el temporizador con ProchuledExecutorService
1) Resuelva el problema uno:
clase pública ProgramedExecutortest {private ProchuledExecutorService Prochuexec; comienzo público largo; ProchuledExecutortest () {this.scheduexec = ejecutors.newscheduledThreadPool (2); this.start = System.CurrentTimemillis (); } public void timerOne () {scheduexec.schedule (new runnable () {public void run () {System.out.println ("TimerOne, the Time:" + (System.CurrentTimemillis () - inicio)); try {Thread.ssleep (4000);} CatchedException e) {E.PrintstActAtree (); }, 1000, TimeUnit.MilliseConds); } public void timertWo () {scheduleExec.schedule (new runnable () {public void run () {System.out.println ("Timertwo, The Time:" + (System.CurrentTimemillis () - Start));}}, 2000, TimeUnit.milliseconds); } public static void main (string [] args) {ProchuleDExeCutortest test = new ProchuledExecutortest (); test.timerone (); test.timertwo (); }} Resultados de ejecución:
Timerone, la hora: 1003
Timertwo, The Time: 2005
2) Resuelva el problema dos
clase pública ProgramedExecutortest {private ProchuledExecutorService Prochuexec; comienzo público largo; ProchuledExecutortest () {this.scheduexec = ejecutors.newscheduledThreadPool (2); this.start = System.CurrentTimemillis (); } public void timerOne () {shedipexec.schedule (new runnable () {public void run () {throw new runtimeException ();}}, 1000, timeUnit.milliseConds); } public void timertWo () {scheduleExec.schedleatfixedRate (new runnable () {public void run () {System.out.println ("Timertwo invocado .....");}}, 2000,500, TimeUnit.milliseConds); } public static void main (string [] args) {ProchuleDExeCutortest test = new ProchuledExecutortest (); test.timerone (); test.timertwo (); }} Resultados de ejecución:
TimeTwo invocado ... TimeTwo Invocado ... TimeTwo Invoced ... TimeTwo Invoced ... TimeTwo Invoced ... Timertwo Invocado ... Timertwo Invocado ... Timertwo invocado ... Timertwo Invocado ... Timertwo invocado ............ TimeTwo Invoced ...................
Lo anterior es todo el contenido de este artículo. Esto se trata de tareas de tiempo Java. Espero que sea útil para su aprendizaje.