1. Visão geral
Implementando a função de executar tarefas regularmente em Java, principalmente usando duas classes, timer e classes Timertosk. O temporizador é usado para executar as tarefas especificadas em um encadeamento de segundo plano de acordo com o plano especificado.
O TimerTask é uma classe abstrata e sua subclasse representa uma tarefa que pode ser planejada pelo timer. O código específico a ser executado está escrito no método de execução que o TimerTask precisa ser implementado.
2. Vamos dar uma olhada no exemplo mais simples
Vamos explicar através do código
importar java.text.simpledEformat; importar java.util.date; importar java.util.timer; importar java.util.timertak; public class TimerDemo {public static string getCurrentTime () {date = new Date (); SimpledateFormat sdf = new SimpleDateFormat ("AAAA-MM-DD HH: MM: SS"); retornar sdf.format (data); } public static void main (string [] args) lança interruptedException {System.out.println ("principal inicial:"+getCurrentTime ()); starttimer (); Thread.sleep (1000*5); // Durma por 5 segundos System.out.println ("END PRINCIPAL:"+getCurrentTime ()); } public static void starttimer () {theTerTask Task = new TimerTask () {@Override public void run () {System.out.println ("Task Run:"+getCurrentTime ()); }}; Timer timer = new Timer (); Timer.Schedule (tarefa, 0); }}Para facilitar as informações de observação por impressão, adicionamos algumas informações de impressão ao método principal e chamamos o Thread.Sleep para fazer com que o encadeamento principal durma. Além disso, um método GetCurrentTime é adicionado à classe para obter a data atual.
No código acima, no método starttimer, é criado um objeto Timertosk (a tarefa a ser executada pelo timer) é criada e um objeto de timer é criado, e o método de cronograma da classe Timer é chamado. A classe Timer possui vários métodos de cronograma com diferentes parâmetros. O que é usado aqui é:
Cronograma de vazios públicos (Tarefa Timertosk, Longo Atraso)
O significado desse método é executar a tarefa de tarefa após o tempo atrasar o tempo (milissegundos). Se o atraso for negativo ou 0, a tarefa será executada imediatamente. E é uma tarefa de execução única, e a tarefa não será repetida (ou programada) posteriormente executada.
Para a classe de temporizador, também é fornecido um método com a mesma função, como segue:
Cronograma de vazios públicos (Tarefa Timertosk, Data Time)
A diferença entre esse método e o método acima é que o método acima especifica que a execução é atrasada por um período de tempo, e esse método especifica que a execução é realizada em um momento específico. Observe que, se o horário atual do sistema tiver excedido o tempo especificado pelo tempo do parâmetro, a tarefa será executada imediatamente.
Ao executar o código acima, descobrimos que o programa imprime imediatamente duas informações semelhantes às seguintes:
Iniciar principal: 2016-01-13 22:23:18
Tarefa Run: 2016-01-13 22:23:18
Como o valor do parâmetro de atraso que passamos para o método de cronograma aqui é 0, a tarefa será executada imediatamente; portanto, o tempo para imprimir as duas instruções é o mesmo, que é o que deve ser. Você pode alterar o valor de atraso recebido por si mesmo para ver as alterações nas informações de saída. Após cerca de 5 segundos (ou seja, horário de sono), continuei a imprimir 1 mensagem:
End principal: 2016-01-13 22:23:23
O tempo para a impressão de informações é de 5 segundos aquém da declaração acima, o que é consistente com a configuração do sono, o que também é muito razoável.
Mas encontraremos um fenômeno muito interessante e descobriremos que o processo não sairá. Neste momento, o encadeamento principal principal terminou. Isso significa que, após o timer concluir a tarefa, mesmo que não haja tarefas esperando para serem executadas posteriormente, o encadeamento de segundo plano criado no timer não sairá imediatamente. Verifiquei a documentação do Doc Java relevante e expliquei que o thread do timer não sairá ativamente e precisa aguardar a coleta de lixo, mas a coleção de lixo de Java não pode ser controlada pelo código em si, mas é controlado pela máquina virtual.
Após a pesquisa, verificou -se que, ao criar um objeto de timer e executar o temporizador do temporizador = new Timer (); Declaração, o thread do timer será criado. Em outras palavras, mesmo que o código acima não tenha o timer.schedule (tarefa, 0); Declaração, o programa não sairá. Eu sinto que isso é bastante irracional. Estudei o código -fonte da classe Timer novamente e descobri que ele também possui um construtor com parâmetros booleanos:
Timer público (Boolean Isdaemon)
Como você pode ver no nome do parâmetro, se o valor do parâmetro for verdadeiro, o thread do timer criado pelo timer é o thread Daemon. O significado de um thread Daemon é que, quando todos os trabalhadores na saída do processo Java, o thread Daemon sai automaticamente.
No momento, precisamos apenas alterar o código para criar o objeto Timer no exemplo acima para: timer timer = new timer (true);
Depois de descobrir que o programa é executado, o programa sairá após o thread principal (o thread principal não é um thread Daemon, mas um thread trabalhador) é concluído, o que significa que o thread do timer também sai, o que significa que, após a adição do parâmetro true, o thread da daemon criado é o thread Daemon.
Mas o problema é que, em cenários de aplicação reais, existem muitos tópicos de trabalhadores em execução e o programa não sairá casualmente. E daí se você quiser que o timer saia ou feche imediatamente? Vamos apresentar isso abaixo.
3. Saída do timer
A classe do temporizador fornece um método de cancelamento para cancelar o timer. Chamar o método Cancelar encerrará esse cronômetro e descartará todas as tarefas agendadas atualmente. Isso não interfere na tarefa atualmente em execução (se existir). Depois que o timer for encerrado, seu thread de execução também será encerrado e não há mais tarefas que possam ser agendadas de acordo com ele.
Observe que, ao chamar esse método dentro do método de execução da tarefa do timer chamada Timer, você pode garantir que a tarefa que está sendo executada seja a última tarefa executada por esse cronômetro. Este método pode ser chamado repetidamente; No entanto, a segunda e as chamadas subsequentes são inválidas.
Vejamos outro código de exemplo:
importar java.text.simpledEformat; importar java.util.date; importar java.util.timer; importar java.util.timertak; public class TimerDemo {public static string getCurrentTime () {date = new Date (); SimpledateFormat sdf = new SimpleDateFormat ("AAAA-MM-DD HH: MM: SS"); retornar sdf.format (data); } public static void main (string [] args) lança interruptedException {System.out.println ("principal inicial:"+getCurrentTime ()); Timer timer = starttimer (); Thread.sleep (1000*5); // Durma por 5 segundos System.out.println ("END PRINCIPAL:"+getCurrentTime ()); Timer.cancel (); } public static timer starttimer () {theTask tarefa = new TimerTask () {@Override public void run () {System.out.println ("Task Run:"+getCurrentTime ()); }}; Timer timer = new Timer (); Timer.Schedule (tarefa, 0); timer de retorno; }} Executar o programa é exatamente o mesmo que a saída do exemplo acima. A diferença é que quando o método principal termina. O processo sairá ativamente, o que significa que o thread do timer foi fechado.
Porque chamamos o método de cancelamento no método principal. Observe que, se você não estiver chamando o método de cancelamento no método de execução do TimerTask, certifique -se de garantir que a tarefa que você deseja executar tenha iniciado ou concluído, caso contrário, se a tarefa não tiver começado a executar. Basta ligar para o cancelamento e todas as tarefas não serão executadas. Por exemplo, o código acima,
Por exemplo, no código acima, se não chamarmos o método de cancelamento no método principal, mas adicione o timer.schedule (tarefa, 0); declaração no método starttimer e adicione o timer.cancel (); Declaração Após a execução, você descobrirá que a tarefa do timer não será executada, pois será cancelada antes que a execução seja concluída.
4. Execute tarefas regularmente
No exemplo acima, estamos introduzindo uma tarefa única, ou seja, o horário do timer chegou. Depois que a tarefa for executada, ela não será repetida mais tarde. Em aplicações reais, existem muitos cenários que exigem que a mesma tarefa seja executada repetidamente regularmente. Existem duas situações: uma é executar tarefas de vez em quando, e a outra é executar tarefas em um determinado (ou vários) momentos todos os dias (ou semanalmente, mensalmente etc.).
Vamos primeiro olhar para o primeiro caso, que é um exemplo de execução da mesma tarefa a cada 10 segundos. O código é o seguinte:
importar java.text.simpledEformat; importar java.util.date; importar java.util.timer; importar java.util.timertak; public class TimerDemo {public static string getCurrentTime () {date = new Date (); SimpledateFormat sdf = new SimpleDateFormat ("AAAA-MM-DD HH: MM: SS"); retornar sdf.format (data); } public static void main (string [] args) lança interruptedException {System.out.println ("principal inicial:"+getCurrentTime ()); starttimer (); } public static void starttimer () {theTerTask Task = new TimerTask () {@Override public void run () {System.out.println ("Task Run:"+getCurrentTime ()); tente {thread.sleep (1000*3); } catch (interruptedException e) {e.printStackTrace (); }}}; Timer timer = new Timer (); Timer.Schedule (Tarefa, 1000*5,1000*10); }} Execute o programa acima e as informações de saída são as seguintes (porque o temporizador não para e a tarefa é repetida, a saída será continuamente emitida. Somente algumas das saídas anteriores são copiadas aqui)
Início principal: 2016-01-14 08:41:14
Tarefa Run: 2016-01-14 08:41:19
Tarefa Run: 2016-01-14 08:41:29
Tarefa Run: 2016-01-14 08:41:39
Tarefa Run: 2016-01-14 08:41:49
Tarefa Run: 2016-01-14 08:42:00
Tarefa Run: 2016-01-14 08:42:10
Tarefa Run: 2016-01-14 08:42:20
Tarefa Run: 2016-01-14 08:42:30
Tarefa Run: 2016-01-14 08:42:40
No código acima, chamamos timer.schedule (tarefa, 1000*5,1000*10); Isso significa que a tarefa é atrasada em 5 segundos e será repetida a cada 10 segundos. Observamos que o tempo de impressão nas informações de saída é o mesmo que o esperado. Além disso, pode -se observar que o intervalo é calculado com base no horário de início da tarefa, ou seja, não deve esperar mais 10 segundos após a conclusão da tarefa.
A classe do temporizador possui dois métodos para implementar essas funções, como segue:
Cronograma de vazios públicos (Tarefa TimerTask, Longo Atraso, Período Longo) Cronograma de Vazio Público (Tarefa Timertosk, Data da primeira hora, período longo)
O primeiro método que usamos acima do código. A diferença entre os dois métodos é a hora da primeira execução. O primeiro método é executado após um atraso especificado de um período de tempo (em milissegundos); O segundo método é executado em um momento especificado.
Neste momento, consideramos o seguinte cenário. Se o tempo de execução de uma tarefa exceder o próximo tempo de espera, o que acontecerá? Vejamos isso através do código:
importar java.text.simpledEformat; importar java.util.date; importar java.util.timer; importar java.util.timertak; public class TimerDemo {public static string getCurrentTime () {date = new Date (); SimpledateFormat sdf = new SimpleDateFormat ("AAAA-MM-DD HH: MM: SS"); retornar sdf.format (data); } public static void main (string [] args) lança interruptedException {System.out.println ("principal inicial:"+getCurrentTime ()); starttimer (); } public static void starttimer () {theTask tarefa = new TimerTask () {@Override public void run () {System.out.println ("Task BEGN:"+getCurrentTime ()); tente {thread.sleep (1000*10); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("Tarefa final:"+getCurrentTime ()); }}; Timer timer = new Timer (); Timer.Schedule (Tarefa, 1000*5,1000*5); }} Comparado com o código anterior, alteramos apenas 2 códigos e modificamos a impressão. Um é alterar o sono no método de execução para 10 segundos, e o outro é alterar o ciclo de execução da tarefa para 5 segundos. Em outras palavras, o tempo de execução da tarefa excede o intervalo entre a execução repetida da tarefa. Execute o programa, a saída anterior é a seguinte:
Iniciar principal: 2016-01-14 09:03:51
Tarefa Begin: 2016-01-14 09:03:56
Fim da tarefa: 2016-01-14 09:04:06
Tarefa Begin: 2016-01-14 09:04:06
Fim da tarefa: 2016-01-14 09:04:16
Tarefa Begin: 2016-01-14 09:04:16
Fim da tarefa: 2016-01-14 09:04:26
Tarefa Begin: 2016-01-14 09:04:26
Fim da tarefa: 2016-01-14 09:04:36
Tarefa Begin: 2016-01-14 09:04:36
Fim da tarefa: 2016-01-14 09:04:46
Tarefa Begin: 2016-01-14 09:04:46
Fim da tarefa: 2016-01-14 09:04:56
Pode -se observar que, após a execução de cada tarefa, a próxima tarefa será executada imediatamente. Como o tempo gasto desde o início da tarefa até a conclusão da tarefa excedeu o intervalo entre a repetição da tarefa, a execução será repetida.
5. Execute tarefas regularmente (repita o ponto de tempo fixo)
Vamos implementar essa função, executar uma tarefa regularmente às 1 da manhã todos os dias, que tem essa função em muitos sistemas, como concluir tarefas de demora e consumir recursos, como backup de dados e estatísticas de dados nesta tarefa. O código é o seguinte:
importar java.text.simpledEformat; importar java.util.calendar; importar java.util.date; importar java.util.timer; importar java.util.timertosk; public class TimerDemo {public static string getCurrenttime () {date = date (); SimpledateFormat sdf = new SimpleDateFormat ("AAAA-MM-DD HH: MM: SS"); retornar sdf.format (data); } public static void main (string [] args) lança interruptedException {System.out.println ("principal inicial:" + getCurrentTime ()); starttimer (); } public static void starttimer () {theTask tarefa = new TimerTask () {@Override public void run () {System.out.println ("Task BEGN:" + getCurrentTime ()); tente {thread.sleep (1000 * 20); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("Tarefa final:" + getCurrentTime ()); }}; Timer timer = new Timer (); Timer.Schedule (Tarefa, BuildTime (), 1000 * 60 * 60 * 24); } data estática privada BuildTime () {calendário calendário = calendário.getInstance (); calendário.set (calendar.hour_of_day, 1); calendário.set (calendário.Minute, 0); calendário.set (calendário.second, 0); Data Hora = calendar.getTime (); se (time.before (new date ())) {// Se o horário atual for após 1 da manhã, 1 dia será necessário, caso contrário, a tarefa será executada imediatamente. // Muitos sistemas geralmente precisam executar tarefas imediatamente quando o sistema iniciar, mas eles precisam executá -los às 1 da manhã todos os dias. O que devo fazer? // É muito simples, basta executar a tarefa separadamente quando o sistema inicializa a chamada (nenhum temporizador é necessário, é apenas o código para executar essa tarefa) time = addday (hora, 1); } tempo de retorno; } data estática privada addday (data, int days) {calendário startdt = calendar.getInstance (); startdt.setTime (data); startdt.add (calendar.day_of_month, dias); return startdt.gettime (); }}Como é executado em intervalos de 24 horas, é impossível aguardar a observação da saída.
6. Resumo
Este artigo apresenta o mecanismo de como executar tarefas cronometradas usando a classe Java Timer. Pode -se observar que ainda existem muitas maneiras de prestar atenção. Nos exemplos introduzidos neste artigo, cada temporizador corresponde a apenas uma tarefa.
O conteúdo introduzido neste artigo pode atender à maioria dos cenários de aplicativos, mas ainda existem alguns problemas, como incluir várias tarefas para um cronômetro? Posso adicionar tarefas novamente depois que o timer for cancelado? Quais outros métodos estão disponíveis na classe do temporizador? Essas perguntas serão apresentadas na postagem do blog a seguir.
Link original: http://www.cnblogs.com/51kata/p/5128745.html
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.