我想在java.utils.Timer中设置一个可重置时间的java.utils.Timer,我需要将一次关闭事件设置为在X秒内发生。如果在创建计时器的时间到X秒之间没有任何反应,则该事件将正常发生。
但是,如果在X秒过去之前,我决定该事件应在Y秒之后发生,那么我希望能够告诉计时器重置其时间,以便该事件在Y秒内发生。
例如。计时器应该能够执行以下操作:
1 2 3 4 5
| 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,它涉及停止原始计时器,并创建一个新计时器。即:
1 2 3
| 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 introduced the java.util.concurrent package and
one of the concurrency utilities therein is the
ScheduledThreadPoolExecutor which is a thread pool for repeatedly
executing tasks at a given rate or delay. It is effectively a more
versatile replacement for the Timer/TimerTask
combination, as it allows multiple service threads, accepts various
time units, and doesn't require subclassing TimerTask (just
implement Runnable). Configuring
ScheduledThreadPoolExecutor with one thread makes it equivalent to
Timer.
如果您的Timer仅将要执行一项任务,那么我建议将其子类化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| 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似乎也没有为重新安排现有任务提供内置支持,但是类似的方法也应该在那里工作。
整个代码段都是这样的....我希望对您有所帮助
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| {
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);
}
}
} |
这就是我正在尝试的方法。我有一个使用TimerTask每60秒轮询一次数据库的类。
在我的主类中,保留Timer的实例以及TimerTask的本地子类的实例。主类有一种方法来设置轮询间隔(例如从60到30)。在其中,我取消了TimerTask(这是我的子类,在这里我重写了cancel()方法以进行一些清理,但这没关系),然后将其设为null。我重新创建它的一个新实例,并在现有Timer中以新的间隔安排新实例。
因为没有取消Timer本身,所以它使用的线程保持活动状态(内部的任何其他TimerTask也会保持活动状态),并且旧的TimerTask被替换为一个新的TimerTask,恰好是相同的,但是VIRGIN(由于旧的将被执行或安排,因此不再是VIRGIN,这是安排所需的)。
当我想关闭整个计时器时,我取消了TimerTask并将其设为空(与我更改计时时所做的相同,同样,是为了清理TimerTask的子类中的资源),然后取消并清空了Timer本身。
我认为使用Timer/TimerTask不可能做到这一点,但是根据您要实现的目标,您可能会对使用java.util.concurrent.ScheduledThreadPoolExecutor感到满意。
您需要安排重复任务吗?在这种情况下,我建议您考虑使用Quartz。
出于类似的目的,我制作了自己的计时器类;随时使用它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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);
}
} |
这里是可重置计时器的示例。为方便起见,请尝试对其进行更改...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| 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...\
");
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秒打印一次当前日期和时间...但是,如果您在控制台中输入任何内容,则计时器将延迟执行给定的输入任务...