Pergunta

Eu gostaria de ter um java.utils.Timer com um tempo reconfigurável em java. Preciso definir um evento único para ocorrer em X segundos.Se nada acontecer entre o momento em que o cronômetro foi criado e X segundos, o evento ocorrerá normalmente.

Se, no entanto, antes de decorridos X segundos, eu decidir que o evento deve ocorrer após Y segundos, então quero poder dizer ao cronômetro para redefinir seu tempo para que o evento ocorra em Y segundos.Por exemplo.o cronômetro deve ser capaz de fazer algo como:

Timer timer = new Timer();  
timer.schedule(timerTask, 5000); //Timer starts in 5000 ms (X)

//At some point between 0 and 5000 ms...  
setNewTime(timer, 8000);  //timerTask will fire in 8000ms from NOW (Y).

Não vejo uma maneira de fazer isso usando o cronômetro de utilitários, pois se você chamar cancel() não poderá agendá-lo novamente.

A única maneira de replicar esse comportamento é usando javax.swing.Timer e envolve parar o cronômetro original e criar um novo.ou seja:

timer.stop();
timer = new Timer(8000, ActionListener);
timer.start();

Existe uma maneira mais fácil??

Foi útil?

Solução

De acordo com Timer documentação, em Java 1.5 em diante, você deve preferir o ScheduledThreadPoolExecutor em vez de.(Você pode querer criar este executor usando Executors.newSingleThreadScheduledExecutor() para facilidade de uso;cria algo muito parecido com um Timer.)

O legal é que quando você agenda uma tarefa (ligando schedule()), ele retorna um ScheduledFuture objeto.Você pode usar isso para cancelar a tarefa agendada.Você estará então livre para enviar uma nova tarefa com um horário de acionamento diferente.

Hora prevista de chegada:O Timer documentação vinculada a não diz nada sobre ScheduledThreadPoolExecutor, No entanto, o OpenJDK versão tinha isto a dizer:

Java 5.0 introduziu o java.util.concurrent pacote e um dos utilitários de concorrência nele é o ScheduledThreadPoolExecutor que é um pool de threads para executar repetidamente tarefas a uma determinada taxa ou atraso.É efetivamente um substituto mais versátil para o Timer/TimerTaskcombinação, pois permite vários tópicos de serviço, aceita várias unidades de tempo e não requer subclassificação TimerTask (apenas implemente Runnable).Configurando ScheduledThreadPoolExecutor com um thread torna equivalente a Timer.

Outras dicas

Se seu Timer só terá uma tarefa para executar, então sugiro subclassificá-la:

import java.util.Timer;
import java.util.TimerTask;

public class ReschedulableTimer extends Timer
{
    private Runnable  task;
    private TimerTask timerTask;

    public void schedule(Runnable runnable, long delay)
    {
        task = runnable;
        timerTask = new TimerTask()
        {
            @Override
            public void run()
            {
                task.run();
            }
        };
        this.schedule(timerTask, delay);
    }

    public void reschedule(long delay)
    {
        timerTask.cancel();
        timerTask = new TimerTask()
        {
            @Override
            public void run()
            {
                task.run();
            }
        };
        this.schedule(timerTask, delay);
    }
}

Você precisará trabalhar no código para adicionar verificações de uso indevido, mas deve conseguir o que deseja.O ScheduledThreadPoolExecutor também não parece ter incorporado suporte para o reprogramamento de tarefas existentes, mas uma abordagem semelhante também deveria funcionar.

Todo o trecho de código é assim ....Espero que seja uma ajuda completa

{

        Runnable r = new ScheduleTask();
        ReschedulableTimer rescheduleTimer = new ReschedulableTimer();
        rescheduleTimer.schedule(r, 10*1000);


    public class ScheduleTask implements Runnable {
        public void run() {
            //Do schecule task

        }
      }


class ReschedulableTimer extends Timer {
        private Runnable task;
        private TimerTask timerTask;

        public void schedule(Runnable runnable, long delay) {
          task = runnable;
          timerTask = new TimerTask() { 
              public void run() { 
                  task.run(); 
                  }
              };

          timer.schedule(timerTask, delay);        
        }

        public void reschedule(long delay) {
            System.out.println("rescheduling after seconds "+delay);
          timerTask.cancel();
          timerTask = new TimerTask() { 
              public void run() { 
                  task.run(); 
              }
          };
          timer.schedule(timerTask, delay);        
        }
      }


}

Você precisa agendar uma tarefa recorrente?Nesse caso, recomendo que você considere usar Quartzo.

Eu não acho que seja possível fazer isso com Timer/TimerTask, mas dependendo do que exatamente você deseja alcançar, você pode ficar satisfeito em usar java.util.concurrent.ScheduledThreadPoolExecutor.

é isso que estou experimentando.Tenho uma classe que pesquisa um banco de dados a cada 60 segundos usando um TimerTask.

na minha classe principal, mantenho a instância do Timer e uma instância da minha subclasse local do TimerTask.a classe principal possui um método para definir o intervalo de pesquisa (digamos, de 60 a 30).nele, cancelo meu TimerTask (que é minha subclasse, onde sobrescrevi o método cancel() para fazer alguma limpeza, mas isso não deveria importar) e depois o torno nulo.eu recrio uma nova instância dele e agendo a nova instância no novo intervalo no temporizador existente.

como o Timer em si não é cancelado, o thread que ele estava usando permanece ativo (e o mesmo aconteceria com qualquer outro TimerTasks dentro dele), e o antigo TimerTask é substituído por um novo, que é o mesmo, mas VIRGIN (já que o TimerTask antigo teria sido executado ou agendado, não é mais VIRGEM, conforme exigido para agendamento).

quando quero desligar o cronômetro inteiro, cancelo e anulo o TimerTask (o mesmo que fiz ao alterar o tempo, novamente, para limpar recursos em minha subclasse de TimerTask) e, em seguida, cancelo e anulo o próprio cronômetro.

Aqui está o exemplo para temporizador reinicializável.Tente alterá-lo para sua conveniência ...

package com.tps.ProjectTasks.TimeThread;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Simple demo that uses java.util.Timer to schedule a task to execute
 * every 5 seconds and have a delay if you give any input in console.
 */

public class DateThreadSheduler extends Thread {  
    Timer timer;
    BufferedReader br ;
    String data = null;
    Date dNow ;
    SimpleDateFormat ft;

    public DateThreadSheduler() {

        timer = new Timer();
        timer.schedule(new RemindTask(), 0, 5*1000); 
        br = new BufferedReader(new InputStreamReader(System.in));
        start();
    }

    public void run(){

        while(true){
            try {
                data =br.readLine();
                if(data != null && !data.trim().equals("") ){
                    timer.cancel();
                    timer = new Timer();
                    dNow = new Date( );
                    ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
                    System.out.println("Modified Current Date ------> " + ft.format(dNow));
                    timer.schedule(new RemindTask(), 5*1000 , 5*1000);
                }

            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String args[]) {
        System.out.format("Printint the time and date was started...\n");
        new DateThreadSheduler();
    }
}

class RemindTask extends TimerTask {
    Date dNow ;
    SimpleDateFormat ft;

    public void run() {

        dNow = new Date();
        ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
        System.out.println("Current Date: " + ft.format(dNow));
    }
}

Este exemplo imprime a data e hora atuais a cada 5 segundos... Mas se você fornecer qualquer entrada no console, o cronômetro será atrasado para executar a tarefa de entrada fornecida...

Criei uma classe de cronômetro própria para um propósito semelhante;Sinta-se livre para usá-lo:

public class ReschedulableTimer extends Timer {
  private Runnable mTask;
  private TimerTask mTimerTask;

  public ReschedulableTimer(Runnable runnable) {
    this.mTask = runnable;
  }

  public void schedule(long delay) {
    if (mTimerTask != null)
      mTimerTask.cancel();

    mTimerTask = new TimerTask() {
      @Override
      public void run() {
        mTask.run();
      }
    };
    this.schedule(mTimerTask, delay);
  }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top