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