Сбрасываемый таймер Java - PullRequest
       43

Сбрасываемый таймер Java

37 голосов
/ 28 августа 2008

Я хотел бы иметь java.utils.Timer с переустанавливаемым временем в java. Мне нужно установить одноразовое событие, которое будет происходить через X секунд. Если между временем создания таймера и X секундами ничего не происходит, событие происходит как обычно.

Если, однако, до истечения X секунд я решу, что событие должно произойти через Y секунд, тогда я хочу сообщить таймеру, чтобы он сбрасывал свое время так, чтобы событие происходило через Y секунд. Например. таймер должен быть в состоянии сделать что-то вроде:

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).

Я не вижу способа сделать это с помощью таймера утилит, так как если вы вызываете метод cancel (), вы не можете запланировать его снова.

Единственный способ, которым я приблизился к репликации этого поведения, - это использование javax.swing.Timer, включающее остановку исходного таймера и создание нового. т.е.:

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

Есть ли более простой способ ??

Ответы [ 8 ]

49 голосов
/ 28 августа 2008

В соответствии с документацией Timer, в Java 1.5 и выше вы должны предпочитать ScheduledThreadPoolExecutor. (Вы можете создать этого исполнителя, используя Executors.newSingleThreadScheduledExecutor() для простоты использования; он создает что-то похожее на Timer.)

Круто то, что когда вы планируете задачу (вызывая schedule()), она возвращает объект ScheduledFuture. Вы можете использовать это, чтобы отменить запланированное задание. После этого вы можете отправить новое задание с другим временем запуска.

ETA: связанная с * документация Timer ничего не говорит о ScheduledThreadPoolExecutor, однако в версии OpenJDK было сказано:

Java 5.0 представила пакет java.util.concurrent и одна из утилит параллелизма - ScheduledThreadPoolExecutor, который является пулом потоков для выполнение заданий с заданной скоростью или задержкой. Это фактически более универсальная замена для Timer / TimerTask комбинация, так как она допускает несколько потоков услуг, принимает различные единицы времени, и не требует подклассов TimerTask (просто реализовать Runnable). Настройка ScheduledThreadPoolExecutor с одним потоком делает его эквивалентным Timer.

17 голосов
/ 28 августа 2008

Если у вашего Timer будет когда-либо только одна задача, то я бы посоветовал создать ее подкласс:

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);
    }
}

Вам нужно будет поработать над кодом, чтобы добавить проверки на неправильное использование, но он должен достичь того, чего вы хотите. ScheduledThreadPoolExecutor, похоже, также не имеет встроенной поддержки для переназначения существующих задач, но аналогичный подход также должен работать там.

3 голосов
/ 27 ноября 2012

Весь фрагмент кода выглядит следующим образом .... Я надеюсь, что это поможет полный

{

        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);        
        }
      }


}
1 голос
/ 16 апреля 2009

это то, что я пробую. У меня есть класс, который опрашивает базу данных каждые 60 секунд, используя TimerTask.

в моем основном классе я храню экземпляр Timer и экземпляр моего локального подкласса TimerTask. В основном классе есть метод для установки интервала опроса (скажем, от 60 до 30). в нем я отменяю свой TimerTask (который является моим подклассом, где я перезаписал метод cancel (), чтобы выполнить некоторую очистку, но это не должно иметь значения), а затем делаю его пустым. я воссоздаю его новый экземпляр и планирую новый экземпляр с новым интервалом в существующем таймере.

, поскольку сам Таймер не отменен, используемый им поток остается активным (как и любые другие TimerTasks внутри него), а старый TimerTask заменяется новым, который оказывается таким же, но VIRGIN (поскольку старый был бы выполнен или запланирован, он больше не является VIRGIN, как требуется для планирования).

когда я хочу выключить весь таймер, я отменяю и обнуляю функцию TimerTask (как и при изменении времени, снова для очистки ресурсов в моем подклассе TimerTask), а затем я отменяю и обнуляю сам таймер .

1 голос
/ 28 августа 2008

Я не думаю, что это возможно сделать с Timer/TimerTask, но в зависимости от того, чего именно вы хотите достичь, вы можете быть счастливы с использованием java.util.concurrent.ScheduledThreadPoolExecutor.

1 голос
/ 28 августа 2008

Вам нужно запланировать повторяющееся задание? В этом случае я рекомендую вам использовать Кварц .

0 голосов
/ 20 июля 2018

Я создал собственный класс таймера для аналогичной цели; не стесняйтесь использовать его:

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);
  }
}
0 голосов
/ 05 декабря 2012

Вот пример для сбрасываемого таймера. Попробуйте изменить это для вашего удобства ...

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));
    }
}

В этом примере печатаются текущие дата и время каждые 5 секунд ... Но если вы введете какие-либо данные в консоли, таймер будет задержан для выполнения заданной задачи ввода ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...