可重置Java定时器

我想在java.I中有一个java.utils.Timer可重置的时间需要设置一个一次性的事件发生在X秒。 如果在创build定时器和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定时器的方法,就像调用cancel()一样,你不能再调度它。

我接近复制这种行为的唯一方法是使用javax.swing.Timer并涉及到停止原始计时器,并创build一个新的。 即:

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

有没有更简单的方法?

根据Timer文档,在Java 1.5之后,你应该更喜欢ScheduledThreadPoolExecutor 。 (你可能喜欢使用Executors .newSingleThreadScheduledExecutor()来创build这个执行Executors以方便使用;它创build了一个很像Timer东西。

很酷的是,当你调度任务(通过调用schedule() )时,它返回一个ScheduledFuture对象。 您可以使用它来取消计划的任务。 然后你可以自由地提交一个不同的触发时间的新任务。

ETA:链接到的Timer文档没有提到有关ScheduledThreadPoolExecutor任何信息,但OpenJDK版本有这样的说法:

Java 5.0引入了java.util.concurrent包,其中的一个并发实用程序是ScheduledThreadPoolExecutor ,它是一个以给定速率或延迟重复执行任务的线程池。 它实际上是Timer / TimerTask组合的更多function的替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要子类化TimerTask (只实现Runnable )。 用一个线程configurationScheduledThreadPoolExecutor使其等价于Timer

如果你的Timer只有一个任务执行,那么我会build议inheritance它:

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

你需要安排一个循环任务吗? 在这种情况下,我build议你考虑使用Quartz 。

我不认为可以用Timer/TimerTask ,但是根据你想要达到的目标,你可能会喜欢使用java.util.concurrent.ScheduledThreadPoolExecutor

这是我正在尝试。 我有一个类每60秒使用一个TimerTask轮询一个数据库。

在我的主类中,我保留了Timer的实例以及TimerTask的本地子类的一个实例。 主类有一个设置轮询间隔的方法(比如从60到30)。 在它中,我取消了我的TimerTask(这是我的子类,在那里我重写了cancel()方法做一些清理,但这应该不重要),然后使其为空。 我重新创build它的一个新的实例,并在现有的计时器中以新的时间间隔安排新的实例。

由于Timer本身并没有被取消,所以它使用的线程仍然保持活动状态(其他任何TimerTasks也是如此),而旧的TimerTask被replace为一个新的,但碰巧是相同的,但是VIRGIN旧的将被执行或计划,它不再是VIRGIN,根据需要调度)。

当我想closures整个计时器,我取消和空的TimerTask(同样,当我改变了时间,再次,清理资源在我的子类的TimerTask),然后我取消和空的计时器本身。

这里是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秒的当前date和时间…但是,如果你在控制台给任何input计时器将延迟执行给定的input任务…