[ScheduledExecutorService] - Aguardar até terminar uma tarefa
10 respostas
lina
Oi,
Precisei agendar uma tarefa para ser executada de 30 em 30 segundos. Para isso, utilizei um ScheduledExecutorService :
scheduleAtFixedRate(newRunnable(){publicvoidrun(){// Processa a tarefa}},30000,TIMER_TIMEOUT,TimeUnit.MILLISECONDS);
Se por acaso neste tempo de 30 segundos a minha tarefa não chegou a terminar (pois existem rotinas complexas e bababa), o scheduleAtFixedRate fará com que inicie uma outra tarefa.
Para que isso não ocorra foi feito:
scheduleAtFixedRate(newRunnable(){publicvoidrun(){try{if(!tarefa_sendo_executada){tarefa_sendo_executada=true;// Processa a tarefa}}finally{tarefa_sendo_executada=!tarefa_sendo_executada;}}},30000,TIMER_TIMEOUT,TimeUnit.MILLISECONDS);
Porém, se o meu processamento da tarefa ficar bloqueado, a função finally nunca será executada e a timer não rodará mais a tarefa.
Seria uma solução passar a utilizar uma simples Thread?
Usar uma simples thread não resolve seu problema também. Será que melhorando a especificação você consegue enxergar melhor o problema? Um exemplo de especificação seria:
agendar uma tarefa de 30 em 30 segundos;
se a tarefa anterior estiver em execução, não deve ser executada outra em paralelo;
o tempo que essa tarefa deve durar não deve exceder 150 segundos - consideraremos que ela ficou “travada” se passar desse tempo;
Porém, se o meu processamento da tarefa ficar bloqueado, a função finally nunca será executada e a timer não rodará mais a tarefa.
se a tarefa anterior estiver em execução, não deve ser executada outra em paralelo;
Oi,
Sim… a grande dificuldade está em saber quando uma tarefa esta em execução. Por isso tentei a variável booleana.
Tchauzin!
E
entanglement
A variável booleana não precisa ser usada se você usar FutureTasks. Eu vou ver se dou um exemplo do que eu falei.
E
entanglement
A minha especificação está incompleta - o que ocorre, por exemplo, se uma tarefa levou 45 segundos em vez de 30? A próxima é iniciada 15 segundos depois (porque você executa uma tarefa de 30 em 30 segundos, mas se ela levou mais tempo que isso você simplesmente “pula” essa vez) ou então você executa a próxima tarefa imediatamente?
lina
Oi,
Aguardo 15 segundos.
Tchauzin!
E
entanglement
Pois bem, olhando a especificação de scheduleAtFixedRate, ele diz que a tarefa pode começar atrasada mas não será pulada. Ou seja, não dá para usar diretamente scheduleAtFixedRate; provavelmente você terá de usar um timer simples, para disparar as tasks, e usar o método cancel para parar algo que demorou demais. O problema chato é que um Future<?> ou um FutureTask<?> é um pouco desacoplado de um Runnable ou Callable, mas você, dentro do seu Runnable ou Callable, provavelmente terá de ter acesso à variável do tipo Future ou FutureTask para checar se sua tarefa foi cancelada, por exemplo.
lina
entanglement:
Pois bem, olhando a especificação de scheduleAtFixedRate, ele diz que a tarefa pode começar atrasada mas não será pulada. Ou seja, não dá para usar diretamente scheduleAtFixedRate; provavelmente você terá de usar um timer simples, para disparar as tasks, e usar o método cancel para parar algo que demorou demais. O problema chato é que um Future<?> ou um FutureTask<?> é um pouco desacoplado de um Runnable ou Callable, mas você, dentro do seu Runnable ou Callable, provavelmente terá de ter acesso à variável do tipo Future ou FutureTask para checar se sua tarefa foi cancelada, por exemplo.
Oi,
Por fim, acho que vou acabar achando uma outra solução. Agora a tarde começarei a ver essa codificação! Minha manhã foi totalmente ocupada por cursores abertos excedidos na base de dados. rs Obrigada!
Tchauzin!
ViniciusLM
Boa tarde pessoal, desculpa se não entendi direto maaaas…
Mas será mesmo que uma thread não resolveria o problema?
chamando uma classe voce pode fazer um loop infinito com o while(true) e no finally voce coloca o tempo que ela deve aguardar até comecar denovo, entao quando ela terminar de fazer a funcao ela passa pelo finally e espera 30 segundo, depois por causa do while ela executa a funcao denovo.
Sim. Dessa forma resolveria. O grande problema é que o tempo de 30seg a 30seg não seria confiável.
Tchauzin!
ViniciusLM
hummm e se vc tentar isso:
cria essa classe que te retorna as horas em milisegundos
Desse jeito ele verifica quanto se passou desde o comeco da ultima execucao, se o tempo for menor que 30000 ele vai esperar a diferenca, por exemplo ele demorou 25 segundos entao segundos = (25000 - 30000) * -1; segundos = 5000.
se ele demorou 45 segundos segundos = (45000 - 30000) * -1; segundos = -15000 dai como é menor que zero entra no while segundos = -15000 + 3000; segundos = 15000 e assim por diante.
Nao estou com muito tempo para fazer mais testes mas sera que ajuda ou não é isso que vc precisa :oops:?