Вопрос

Я бы хотел иметь java.utils.Таймер с возможностью сброса времени в 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).

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

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

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

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

Это было полезно?

Решение

В соответствии с 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.

Другие советы

Если ваш 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 похоже, что в нем также нет встроенной поддержки для перепланирования существующих задач, но аналогичный подход должен работать и там.

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

{

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


}

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

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

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

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

поскольку сам Таймер не отменяется, поток, который он использовал, остается активным (как и любые другие временные задачи внутри него), а старая временная задача заменяется новой, которая оказывается такой же, но НЕТРОНУТОЙ (поскольку старая была бы выполнена или запланирована, она больше не является НЕТРОНУТОЙ, как требуется для планирования).

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

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

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 секунд...Но если вы введете какие-либо данные в консоли, таймер будет отложен для выполнения заданной задачи ввода...

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

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);
  }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top