Se precisarmos executar algumas tarefas de tempo simples durante o nosso processo de programação, não precisamos fazer controle complexo. Podemos considerar o uso de tarefas de tempo do timer no JDK para alcançá -lo. O LZ a seguir analisa o timer Java com base em seu princípio, exemplo e defeito do timer.
1. Introdução
Em Java, uma tarefa de tempo completa precisa ser concluída pelas classes de timer e Timertosk. É assim que eles são definidos na API. Timer: Uma ferramenta que a usa para organizar tarefas que os threads executam nos threads em segundo plano posteriormente. As tarefas podem ser executadas uma vez ou podem ser executadas repetidamente. Tarefa agendada por TimerTask: Timer como uma tarefa executada ou repetida. Podemos entender que o timer é uma ferramenta de timer usada para planejar para executar tarefas especificadas em um encadeamento de segundo plano e o TimerTask uma classe abstrata cuja subclasse representa uma tarefa que pode ser planejada pelo timer.
Classe do temporizador <Br /> No timer da classe de ferramentas, quatro métodos de construtor são fornecidos. Cada construtor inicia um thread timer. Ao mesmo tempo, a classe do temporizador pode garantir que vários threads possam compartilhar um único objeto de temporizador sem sincronização externa, para que a classe do timer seja segura por threads. No entanto, como cada objeto de timer corresponde a um único thread de fundo, usado para executar todas as tarefas do timer em sequência, em geral, o tempo gasto na execução da nossa tarefa de thread deve ser muito curto. No entanto, devido a circunstâncias especiais, o tempo de execução de uma determinada tarefa do timer é muito longo, por isso será "exclusivamente" o encadeamento de execução da tarefa do timer, e todos os threads subsequentes devem aguardar a execução, o que atrasará a execução das tarefas subsequentes e tornará essas tarefas se acumularem. Analisaremos a situação específica mais tarde.
Quando o programa inicializa o cronômetro, a tarefa de tempo será executada de acordo com o momento em que definimos. O timer fornece o método de cronograma, que possui várias sobrecargas para se adaptar a diferentes situações, como segue:
Agenda (Tarefa TimerTask, Data de Data): Programe a execução da tarefa especificada no horário especificado.
Cronograma (Tarefa TimerTask, Data da primeira hora, período longo): Programe a tarefa especificada para iniciar a execução de atraso fixo repetido no horário especificado.
Cronograma (Tarefa TimerTask, Longo Atraso): Agenda a tarefa especificada a ser executada após o atraso especificado.
Cronograma (Tarefa TimerTask, Longo Atraso, Período Longo): Programe a tarefa especificada a ser executada repetidamente atrasada após o atraso especificado.
Ao mesmo tempo, o método ScheduleatFixedrate também está sobrecarregado. O método ScheduleatFixedrate é o mesmo que o cronograma, mas o foco deles é diferente e a diferença é analisada posteriormente.
ScheduleAtFixEdRate (Tarefa TimerTask, Data FirstTime, Longo Período): Programe a tarefa especificada a ser executada repetidamente a uma taxa fixa em um horário especificado.
ScheduleAtFixEdRate (Tarefa TimerTask, Longo Atraso, Período Longo): Programe a tarefa especificada para iniciar a execução de taxa fixa repetida após o atraso especificado.
TimerTask
A classe Timertosk é uma classe abstrata organizada pelo timer como uma tarefa que é executada ou repetida. Possui um método abstrato de execução (), usado para executar as operações a serem executadas pela tarefa do timer correspondente. Portanto, cada classe de tarefa específica deve herdar TimerTask e substituir o método run ().
Além disso, possui dois métodos não abstratos:
boolean cancel (): cancele esta tarefa do timer.
Long ScheduleDexecutionTime (): Retorna o tempo de execução programado da execução real mais recente desta tarefa.
2. Exemplos
2.1. Especifique o tempo de atraso para executar tarefas de tempo
classe pública TimeTerTest01 {Timer Timer; public timeTerTest01 (int time) {timer = new Timer (); Timer.Schedule (novo TimerTaskTest01 (), tempo * 1000); } public static void main (string [] args) {System.out.println ("Timer começa ..."); novo TimeTerTest01 (3); }} classe pública TimerTaskTest01 estende o TimerTask {public void run () {System.out.println ("Time está pronto !!!"); }} Resultados em execução:
Primeira impressão: Timer começa ...
Imprima em 3 segundos: o tempo está!
2.2. Executar tarefas de tempo no horário especificado
classe pública TimeTerTest02 {Timer Timer; public timeTerTest02 () {Data Hora = getTime (); System.out.println ("Especificar tempo =" + tempo); Timer = new Timer (); Timer.Schedule (novo TimerTaskTest02 (), Time); } public date gettime () {calendário calendário = calendar.getInstance (); calendário.set (calendar.hour_of_day, 11); calendário.set (calendário.Minute, 39); calendário.set (calendário.second, 00); Data Hora = calendar.getTime (); tempo de retorno; } public static void main (string [] args) {new TimeTerTest02 (); }} classe pública TimerTaskTest02 estende o TimerTask {@Override public void run () {System.out.println ("Execute as tarefas do encadeamento no tempo especificado ..."); }} Quando o horário chegar às 11:39:00, a tarefa do tópico será executada, é claro, será executada mesmo que seja maior que a época! ! O resultado da execução é:
Tempo especificado = Ter, 10 de junho 11:39:00 CST 2014
Executar tarefas de encadeamento no horário especificado ...
2.3. Depois de atrasar o tempo especificado, a tarefa de tempo será executada no tempo de intervalo especificado.
classe pública TimeTerTest03 {Timer Timer; public timeTerTest03 () {Timer = new Timer (); Timer.Schedule (novo TimerTaskTest03 (), 1000, 2000); } public static void main (string [] args) {new TimeTerTest03 (); }} classe pública TimerTaskTest03 estende o TimerTask {@Override public void run () {Date = new Date (this.scheduledExecutionTime ()); System.out.println ("O tempo para executar este thread é:" + data); }} Resultados em execução:
O tempo para executar este tópico é: Ter 10 de junho 21:19:47 CST 2014
O tempo para executar este tópico é: Ter 10 de junho 21:19:49 CST 2014
O tempo para executar este tópico é: Ter 10 de junho 21:19:51 CST 2014
O tempo para executar este tópico é: Ter 10 de junho 21:19:53 CST 2014
O tempo para executar este tópico é: Ter 10 de junho 21:19:55 CST 2014
O tempo para executar este tópico é: Ter 10 de junho 21:19:57 CST 2014
................
Para esta tarefa de thread, se não interrompermos a tarefa, ela continuará sendo executada.
Para os três exemplos acima, o LZ apenas o demonstrou e não explicou o exemplo do método ScheduleatFixedrate. De fato, esse método é o mesmo que o método do cronograma!
2.4. Analise o cronograma e o ScheduleatFixedrate
1), cronograma (tarefa do TimerTask, data de data), cronograma (tarefa do Timertosk, longo atraso)
Para ambos os métodos, se o ScheduledExecutionTime especificado <= SystemCurrentTime, a tarefa será executada imediatamente. O ScheduleDexecutionTime não mudará devido à execução excessiva de uma tarefa.
2) Cronograma (tarefa do TimerTask, data na primeira hora, período longo), cronograma (tarefa do TimerTask, atraso longo, longo período)
Esses dois métodos são um pouco diferentes dos dois acima. Como mencionado anteriormente, a tarefa do timer do timer será adiada porque a tarefa anterior é executada por um longo tempo. Nesses dois métodos, o horário programado de cada tarefa executada mudará com o tempo real da tarefa anterior, ou seja, ScheduleDexecutionTime (n+1) = reelexecutionTime (n)+periódico. Ou seja, se a enxada tarefa causar esse processo de tempo de execução devido a alguma situação e, finalmente, SystemCurrentTime> = ScheduleDexecutionTime (n+1), esta é a tarefa n+1 e não será executada devido ao tempo. Ele aguardará a enésima tarefa ser executada antes da execução, então isso inevitavelmente levará à implementação de execução N+2, scheduledExecution time de liberação e alteração, ou seja, scheduledExecutionTime (n+2) = reelexecutionTime (n+1)+periódico. Portanto, esses dois métodos prestam mais atenção à estabilidade do tempo de intervalo de armazenamento.
3) ScheduleAtFixedRate (Tarefa TimerTask, Data FirstTime, Longo Período), ScheduleAtFixedrate (Tarefa TimerTask, Longo Atraso, Período Longo)
Como mencionado anteriormente, o foco dos métodos ScheduleAtFixedrate e Cronogram é diferente. O método de cronograma se concentra na estabilidade do tempo de intervalo de economia, enquanto o método ScheduleatFixedrate se concentra mais na manutenção da estabilidade da frequência de execução. Por que você diz, as razões são as seguintes. No método do cronograma, o atraso da tarefa anterior causará o atraso da tarefa de tempo depois dela, enquanto o método ScheduleatFixedrate não o fará. Se o tempo de execução da enésima tarefa for muito longo, o SystemCurrentTime> = ScheduleDexecutionTime (n+1), não haverá nenhuma espera para executar a tarefa N+1 imediatamente. Portanto, o método de cálculo do tempo de execução do método ScheduleAtFixedrate é diferente do cronograma, mas o ScheduleDexecutionTime (n) = FirstExecutETime +N*perious e o método de cálculo permanecerá inalterado para sempre. Portanto, o ScheduleAtFixedrate se concentra mais em manter a frequência de execução estável.
3. Defeitos do timer
3.1. Defeitos do timer
O timer pode horário (executar tarefas no horário especificado), atraso (atraso de tarefas em 5 segundos) e executar periodicamente tarefas (execute tarefas em 1 segundo), mas o timer tem algumas deficiências. Primeiro de tudo, o suporte do Timer para agendamento é baseado no tempo absoluto, não no tempo relativo, por isso é muito sensível às mudanças no tempo do sistema. Em segundo lugar, o tópico do timer não captará exceções. Se a exceção desmarcada for lançada pelo TimerTask, fará com que o thread do timer termine. Ao mesmo tempo, o cronômetro não retomará a execução do thread e acreditará erroneamente que todo o thread do timer será cancelado. Ao mesmo tempo, o TimerTask, que foi agendado para ainda não executado, não será mais executado e novas tarefas não podem ser agendadas. Portanto, se o Timertosk lançar uma exceção desmarcada, o timer produzirá um comportamento imprevisível.
1) Defeito no atraso do tempo de gerenciamento do timer <r /> O timer anterior criará apenas uma tarefa de thread ao executar uma tarefa cronometrada. Se houver vários threads, se um dos threads fizer com que o tempo de execução da tarefa de threads seja muito longo por algum motivo, e o intervalo entre as duas tarefas excede o tempo entre eles, alguns defeitos ocorrerão:
classe pública TimeTerTest04 {Timer privado; Public Long Start; public timeTerTest04 () {this.timer = new Timer (); start = system.currenttimemillis (); } public void timerone () {timer.schedule (new TimerTask () {public void run () {System.out.println ("timerone invocou, o tempo:" + (system.curnttimEmillis () - start); Try {thread.Sleep (4000) // }}}}, 1000); } public void timerTwo () {timer.schedule (new timerTask () {public void run () {System.out.println ("timerone invocou, o tempo:" + (System.currenttimemillis () - start));}, 3000); } public static void main (string [] args) lança exceção {timeTerTest04 test = new TimeTerTest04 (); test.timerone (); test.timertwo (); }} De acordo com nosso pensamento normal, TimerTwo deve ser executado após 3s, e o resultado deve ser:
Timerone invocou, o tempo: 1001
Timerone invocou, o tempo: 3001
Mas as coisas foram contra minhas expectativas. Timerone dorme (4000), dorme 4s, e o temporizador está dentro do temporizador, o que causa o tempo necessário para que o TimeOne exceda o intervalo. O resultado:
Timerone invocou, o tempo: 1000
Timerone invocou, o tempo: 5000
2) O timer lança defeito de exceção
Se o TimerTask lançar uma hora de execução, o timer encerrará todas as tarefas. do seguinte modo:
classe pública TimeTerTest04 {Timer privado; public timeTerTest04 () {this.timer = new Timer (); } public void timerone () {timer.schedule (new timerTask () {public void run () {throw novo RunTimeException ();}}, 1000); } public void timerTwo () {timer.schedule (new timerTask () {public void run () {System.out.println ("Vou executá -lo ??");}}, 1000); } public static void main (string [] args) {timeTerTest04 test = new Timertest04 (); test.timerone (); test.timertwo (); }} Resultado em execução: Timerone lança uma exceção, fazendo com que a tarefa TimerTwo termine.
Exceção em thread "Timer-0" java.lang.runtimeException em com.chenssy.timer.timertest04 $ 1.run (timetest04.java:25) em java.util.timerthread.mainloop (timer.java:55) em java.util.timherths.rain.rainloop (timer.java:55) em java.util.timherth.ra.
Para os defeitos do timer, podemos considerar o ScheduledThreadpoolExecutor como um substituto. O timer é baseado no tempo absoluto e é mais sensível ao tempo do sistema, enquanto o ScheduledThreadPoolExector é baseado no tempo relativo; O timer é um único thread internamente, enquanto o ScheduledThreadpoolExecutor é um pool de threads internamente, para que possa suportar a execução simultânea de várias tarefas.
3.2. Substitua o temporizador pelo ScheduledExecutorService
1) Resolva o problema:
classe pública ScheduleDexectestest {private ScheduleDexecutorService Scheduexec; Public Long Start; ScheduledExecutorTest () {this.scheduexec = executores.newscheduledThreadpool (2); this.start = system.currenttimemillis (); } public void timeRone () {scheduexec.schedule (new runnable () {public void run () {System.out.println ("timerone, the the the the time:" + (system.currenttimEmillis () - start); try {thread.sleep (4000);} catch (interncexcent () - start); try {thread.sleep (4000);} Catch () }, 1000, timeUnit.millisEconds); } public void timertwo () {scheduleexec.schedule (new runnable () {public void run () {System.out.println ("timetwo, the the the time:" + (system.currenttimemillis () - start); } public static void main (string [] args) {scheduledExecutorTest test = new ScheduleDexecutorTest (); test.timerone (); test.timertwo (); }} Resultados em execução:
Timerone, o tempo: 1003
Timertwo, The Time: 2005
2) Resolva o problema dois
classe pública ScheduleDexectestest {private ScheduleDexecutorService Scheduexec; Public Long Start; ScheduledExecutorTest () {this.scheduexec = executores.newscheduledThreadpool (2); this.start = system.currenttimemillis (); } public void timerone () {scheduexec.schedule (new runnable () {public void run () {tiro new RunTimeException ();}}, 1000, timeUnit.millisEconds); } public void timertwo () {scheduleexec.scheduleatfixedrate (new runnable () {public void run () {System.out.println ("timertwo invocou .....");}}, 2000.500, timeUnit.millisEconds); } public static void main (string [] args) {scheduledExecutorTest test = new ScheduleDexecutorTest (); test.timerone (); test.timertwo (); }} Resultados em execução:
Timertwo invocou ... Timertwo invocou ... Timertwo invocou ... Timertwo invocou ... Timertwo invocou ... Timertwo invocou ... Timertwo invocou ... TimerTwo invocou ... Timertwo invocou ... Timertwo invocou ............
O acima é o conteúdo inteiro deste artigo. Isso se trata de tarefas de tempo de Java. Espero que seja útil para o seu aprendizado.