所以我想尝试一下Timer和TimerTask类。
我能够让一行代码在30秒后执行。我现在要做的是让这行代码执行5分钟。
这是我最初尝试的
public static void main(String[] args)
{
for ( int i = 0; i <= 10; i ++ )
{
Timer timer = new Timer();
timer.schedule( new TimerTask()
{
public void run()
{
System.out.println("30 Seconds Later");
}
}, 30000
);
}
}
我在for循环中使用了数字10来查看计时器是否。Schedule将在循环的下一次迭代中再等待30秒。
你知道我该怎么做吗?我尝试使用schedule方法,传入一个参数,但这只会使它重新执行,它永远不会停止。
Java在java.util.concurrent
包中提供了一组丰富的api来实现这些任务。其中一个api是ScheduledExecutorService
。例如,考虑下面给出的代码:这段代码将在每30
秒后执行Runnable
task
,持续5
分钟:
import java.util.concurrent.*;
class Scheduler
{
private final ScheduledExecutorService service;
private final long period = 30;//Repeat interval
public Scheduler()
{
service = Executors.newScheduledThreadPool(1);
}
public void startScheduler(Runnable runnable)
{
final ScheduledFuture<?> handler = service.scheduleAtFixedRate(runnable,0,period,TimeUnit.SECONDS);//Will cause the task to execute after every 30 seconds
Runnable cancel = new Runnable()
{
@Override
public void run()
{
handler.cancel(true);
System.out.println("5 minutes over...Task is cancelled : "+handler.isCancelled());
}
};
service.schedule(cancel,5,TimeUnit.MINUTES);//Cancels the task after 5 minutes
}
public static void main(String st[])
{
Runnable task = new Runnable()//The task that you want to run
{
@Override
public void run()
{
System.out.println("I am a task");
}
};
Scheduler sc = new Scheduler();
sc.startScheduler(task);
}
}
您遇到的问题是调度的Timer
在不同的线程上运行-也就是说,for
循环的下一次迭代在调度后立即开始运行,而不是30秒后。看起来你的代码一次启动十个计时器,这意味着它们应该(大约)在30秒后全部打印出来。
当您尝试使用schedule
的循环版本(带第三个参数)时,您在正确的轨道上。正如您所注意到的,这不是您想要的,因为它无限期地运行。然而,Timer
确实有一个cancel
方法来防止后续的执行。
所以,你应该尝试这样做:
final Timer timer = new Timer();
// Note that timer has been declared final, to allow use in anon. class below
timer.schedule( new TimerTask()
{
private int i = 10;
public void run()
{
System.out.println("30 Seconds Later");
if (--i < 1) timer.cancel(); // Count down ten times, then cancel
}
}, 30000, 30000 //Note the second argument for repetition
);
这是一个我羞于展示的变通方法:
package test;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class FiveMinutes {
private static int count = 0;
// main method just to add example
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("Count is: " + count);
if (count == 1) {
System.err.println("... quitting");
System.exit(0);
}
count++;
}
},
// starting now
new Date(),
// 5 minutes
300000l
);
}
}
还请注意,应用程序可能不会精确地运行 5分钟-参见TimerTask文档。
您的解决方案非常接近工作,您只需将延迟乘以计数器(在您的情况下为i
):
public static void main(String[] args)
{
for (int i = 1; i <= 10; i++) // start i at 1 for initial delay
{
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run()
{
System.out.println("30 Seconds Later");
}
}, 30000 * i); // 5 second intervals
}
}
我不知道这个解决方案是否与垃圾收集器有问题,但我还是把它扔在这里。也许有人把它清除了,我也学到了一些东西。基本上定时器设置一个新的定时器,如果还有时间,它应该在5分钟后停止。
Main.java:
public class Main {
public static void main(String[] args) {
MyTimer myTimer = new MyTimer(300000,30000);
myTimer.startTimer();
}
}
MyTimer.java:
import java.util.Timer;
import java.util.TimerTask;
public class MyTimer {
private int totalRunningTime;
private int currentTime = 0;
private int intervalTime;
private Timer timer = new Timer();
public MyTimer(int totalRunningTime, int intervalTime) {
this.totalRunningTime = totalRunningTime;
this.intervalTime = intervalTime;
}
public void startTimer() {
startTimer(intervalTime);
}
private void startTimer(int time) {
timer.schedule(new TimerTask() {
public void run() {
if (currentTime <= totalRunningTime - intervalTime) {
printTimeSinceLast(intervalTime / 1000);
currentTime += intervalTime;
startTimer(intervalTime);
} else if (currentTime < totalRunningTime) {
int newRestIntervalTime = totalRunningTime - currentTime;
printTimeSinceLast(newRestIntervalTime / 1000);
currentTime += newRestIntervalTime;
startTimer(newRestIntervalTime);
}
}
}, time);
}
private void printTimeSinceLast(int timeSinceLast) {
System.out.println(timeSinceLast + " seconds later.");
}
}