Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Если у вашего 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

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

{

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


}

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

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

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

Ответ 7

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

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