Encontrei perguntas semelhantes feitas aqui, mas não havia respostas para minha satisfação. Então, reformulando a pergunta novamente-
Tenho uma tarefa que precisa ser feita periodicamente (digamos, intervalos de 1 minuto). Qual é a vantagem de usar o Timertask & Timer para fazer isso em vez de criar um novo encadeamento que tem um loop infinito com suspensão?
Snippet de código usando timertask-
TimerTask uploadCheckerTimerTask = new TimerTask(){
public void run() {
NewUploadServer.getInstance().checkAndUploadFiles();
}
};
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);
Snippet de código usando Thread e sleep-
Thread t = new Thread(){
public void run() {
while(true) {
NewUploadServer.getInstance().checkAndUploadFiles();
Thread.sleep(60 * 1000);
}
}
};
t.start();
Eu realmente não preciso me preocupar se perder certos ciclos se a execução da lógica levar mais do que o tempo de intervalo.
Por favor, comente sobre isso ..
Atualização:
Recentemente descobri outra diferença entre usar Timer e Thread.sleep (). Suponha que a hora atual do sistema seja 11h. Se revertermos a hora do sistema para 10:00 AM por algum motivo, o Timer irá PARAR a execução da tarefa até chegar às 11:00, enquanto o método Thread.sleep () continuará executando a tarefa sem obstáculos. Este pode ser um grande tomador de decisões ao decidir o que usar entre os dois.
Respostas:
A vantagem do TimerTask é que ele expressa sua intenção muito melhor (ou seja, legibilidade do código) e já possui o recurso cancel () implementado.
Observe que ele pode ser escrito em uma forma mais curta, bem como em seu próprio exemplo:
fonte
Timer / TimerTask também leva em consideração o tempo de execução de sua tarefa, por isso será um pouco mais preciso. E lida melhor com problemas de multithreading (como evitar deadlocks etc.). E, claro, geralmente é melhor usar um código padrão bem testado em vez de alguma solução caseira.
fonte
Eu não sei por que, mas um programa que eu estava escrevendo estava usando Timers e seu tamanho de heap estava aumentando constantemente, uma vez que eu mudei para Thread / problema de sono resolvido.
fonte
Se você thread obtiver exceção e for eliminado, isso é um problema. Mas o TimerTask cuidará disso. Ele será executado independentemente de falha na execução anterior.
fonte
Da
Timer
documentação :Portanto, prefira em
ScheduledThreadExecutor
vez deTimer
:Timer
usa um único thread de segundo plano que é usado para executar todas as tarefas do temporizador, sequencialmente. Portanto, as tarefas devem ser concluídas rapidamente, caso contrário, isso atrasará a execução das tarefas subsequentes. Mas no caso deScheduledThreadPoolExecutor
podemos configurar qualquer número de threads e também podemos ter controle total, fornecendoThreadFactory
.Timer
pode ser sensível ao relógio do sistema, pois faz uso doObject.wait(long)
método. MasScheduledThreadPoolExecutor
não é.ScheduledThreadPoolExecutor
forma que as outras tarefas não sejam afetadas.Timer
fornece umcancel
método para encerrar o cronômetro e descartar todas as tarefas agendadas, no entanto, não interfere na tarefa em execução no momento e permite que ela termine. Mas se o timer estiver rodando como um daemon thread, quer o cancelemos ou não, ele terminará assim que todos os threads do usuário terminarem de ser executados.Timer vs Thread.sleep
Timer faz uso de
Object.wait
e é diferente deThread.sleep
wait
thread em espera ( ) pode ser notificado (usandonotify
) por outro thread, mas um thread em não pode ser, ele só pode ser interrompido.fonte
Há um argumento crucial contra o gerenciamento dessa tarefa usando
sleep
métodos e threads de Java . Você está usandowhile(true)
para permanecer indefinidamente no loop e hibernar o thread colocando-o no modo de espera. E seNewUploadServer.getInstance().checkAndUploadFiles();
ocupar alguns recursos sincronizados. Outros threads não conseguirão acessar esses recursos. A inanição pode ocorrer, o que pode tornar todo o seu aplicativo lento. Esses tipos de erros são difíceis de diagnosticar e é uma boa ideia prevenir sua existência.A outra abordagem dispara a execução do código que importa para você, ou seja
NewUploadServer.getInstance().checkAndUploadFiles();
, chamando orun()
método do seuTimerTask
enquanto permite que outras threads usem os recursos.fonte
Acho que entendo seu problema, estou vendo algo muito semelhante. Tenho temporizadores que são recorrentes, alguns a cada 30 minutos e alguns a cada dois dias. Pelo que li e pelos comentários que vejo, parece que a coleta de lixo nunca será executada porque todas as tarefas nunca são concluídas. Eu pensaria que a coleta de lixo seria executada quando um cronômetro está em hibernação, mas não estou vendo e de acordo com a documentação, não.
Eu acho que a geração de novos threads conclui e permite a coleta de lixo.
Alguém, por favor, prove que estou errado, reescrever o que herdei vai ser uma dor.
fonte