Temporizador Java
1. Timer - o básico
2. Agende uma tarefa uma vez
Vamos começar simplesmenterunning a single task com a ajuda deTimer:
@Test
public void givenUsingTimer_whenSchedulingTaskOnce_thenCorrect() {
TimerTask task = new TimerTask() {
public void run() {
System.out.println("Task performed on: " + new Date() + "n" +
"Thread's name: " + Thread.currentThread().getName());
}
};
Timer timer = new Timer("Timer");
long delay = 1000L;
timer.schedule(task, delay);
}
Observe que se estivermos executando este é um teste JUnit, devemos adicionar uma chamadaThread.sleep(delay * 2) para permitir que o encadeamento do Timer execute a tarefa antes que o teste Junit pare de ser executado.
3. Agende uma tarefa repetida em um intervalo
Em seguida - vamosschedule a task to run at a pre-defined interval.
Faremos uso da APIscheduleAtFixedRate(repeatedTask, delay, period) - que agenda a tarefa para execução repetida de taxa fixa, começando após o atraso especificado. As execuções subsequentes ocorrem em intervalos regulares, separadas pelo período especificado:
@Test
public void givenUsingTimer_whenSchedulingRepeatedTask_thenCorrect(){
TimerTask repeatedTask = new TimerTask() {
public void run() {
System.out.println("Task performed on " + new Date());
}
};
Timer timer = new Timer("Timer");
long delay = 1000L;
long period = 1000L;
timer.scheduleAtFixedRate(repeatedTask, delay, period);
}
Observe que - se uma execução for atrasada por qualquer motivo (como coleta de lixo ou outra atividade em segundo plano), duas ou mais execuções ocorrerão em rápida sucessão para "recuperar o atraso".
3.1. Agende uma tarefa diária
A seguir - vamosrun a task once a day:
@Test
public void givenUsingTimer_whenSchedulingDailyTask_thenCorrect() {
TimerTask repeatedTask = new TimerTask() {
public void run() {
System.out.println("Task performed on " + new Date());
}
};
Timer timer = new Timer("Timer");
long delay = 1000L;
long period = 1000L * 60L * 60L * 24L;
timer.scheduleAtFixedRate(repeatedTask, delay, period);
}
4. CancelarTimer eTimerTask
A execução de uma tarefa pode ser cancelada de algumas maneiras:
4.1. Cancele oTimerTask dentro deRun
Chamando o métodoTimerTask.cancel() dentro da implementação do métodorun() do próprioTimerTask:
@Test
public void givenUsingTimer_whenCancelingTimerTask_thenCorrect()
throws InterruptedException {
TimerTask task = new TimerTask() {
public void run() {
System.out.println("Task performed on " + new Date());
cancel();
}
};
Timer timer = new Timer("Timer");
timer.scheduleAtFixedRate(task, 1000L, 1000L);
Thread.sleep(1000L * 2);
}
4.2. Cancelar oTimer
Chamando o métodoTimer.cancel() em um objetoTimer:
@Test
public void givenUsingTimer_whenCancelingTimer_thenCorrect()
throws InterruptedException {
TimerTask task = new TimerTask() {
public void run() {
System.out.println("Task performed on " + new Date());
}
};
Timer timer = new Timer("Timer");
timer.scheduleAtFixedRate(task, 1000L, 1000L);
Thread.sleep(1000L * 2);
timer.cancel();
}
4.3. Pare a linha deTimerTask dentro deRun
Você também pode interromper o encadeamento dentro do métodorun da tarefa, cancelando assim a tarefa inteira:
@Test
public void givenUsingTimer_whenStoppingThread_thenTimerTaskIsCancelled()
throws InterruptedException {
TimerTask task = new TimerTask() {
public void run() {
System.out.println("Task performed on " + new Date());
// TODO: stop the thread here
}
};
Timer timer = new Timer("Timer");
timer.scheduleAtFixedRate(task, 1000L, 1000L);
Thread.sleep(1000L * 2);
}
Observe a instrução TODO na implementação derun - para executar este exemplo simples, precisaremos realmente parar o thread.
Em uma implementação de thread customizada do mundo real, a interrupção do thread deve ser suportada, mas neste caso podemos ignorar a reprovação e usar a APIstop simples na própria classe Thread.
5. Timer VSExecutorService
Você também pode fazer bom uso de um ExecutorService para agendar tarefas do cronômetro, em vez de usá-lo.
Aqui está um exemplo rápido de como executar uma tarefa repetida em um intervalo especificado:
@Test
public void givenUsingExecutorService_whenSchedulingRepeatedTask_thenCorrect()
throws InterruptedException {
TimerTask repeatedTask = new TimerTask() {
public void run() {
System.out.println("Task performed on " + new Date());
}
};
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
long delay = 1000L;
long period = 1000L;
executor.scheduleAtFixedRate(repeatedTask, delay, period, TimeUnit.MILLISECONDS);
Thread.sleep(delay + period * 3);
executor.shutdown();
}
Então, quais são as principais diferenças entre a soluçãoTimereExecutorService:
-
Timer pode ser sensível a mudanças no relógio do sistema; ScheduledThreadPoolExecutor não é
-
Timer tem apenas um thread de execução; ScheduledThreadPoolExecutor pode ser configurado com qualquer número de threads
-
As exceções de tempo de execução lançadas dentro deTimerTask eliminam o encadeamento, portanto, as tarefas agendadas seguintes não funcionarão mais; comScheduledThreadExecutor - a tarefa atual será cancelada, mas o resto continuará a ser executado
6. Conclusão
Este tutorial ilustrou as várias maneiras de usar a infraestrutura simples, porém flexível,TimereTimerTask integrada em Java para agendar tarefas rapidamente. É claro que existem soluções muito mais complexas e completas no mundo Java se você precisar delas - comothe Quartz library - mas este é um bom lugar para começar.
A implementação desses exemplos pode ser encontrada emthe github project - este é um projeto baseado em Eclipse, portanto, deve ser fácil de importar e executar como está.