0

我正在尝试每 5 分钟执行一次任务。任务需要从:xx:00、xx:05、xx:10、xx:15 等开始,所以如果时间是 xx:37,任务将从 xx:40 开始。

我使用以下代码来做到这一点:

    Date d1 = new Date();
    d1.setMinutes(d1.getMinutes() + 5 - d1.getMinutes()%5);
    d1.setSeconds(0);
    this.timer.schedule(new Send(), d1, TEN_MINUTES/2);

发送看起来像这样:

class Send extends TimerTask
{
    public void run()
    {
        if(SomeCondition)
                    {
                            Timestamp ts1 = new Timestamp(new java.util.Date().getTime());
                            SendToDB(ts1);
                    }
    }
}

所以结果应该是记录,如果你 % 分钟,结果将为 0。但我所拥有的记录时间是:

*05:35:00 *07:44:40 *07:54:40 *09:05:31 *09:50:00

正如您所看到的,第一个任务完美地开始了,但随后出现了问题。

我的猜测是该任务会在上一个任务完成后计算 5 分钟的跳转,因此任务运行时间会受到影响,但这只是一个猜测。

4

3 回答 3

2

任务执行所需的时间会延迟计划。从文档中schedule

如果由于任何原因(例如垃圾收集或其他后台活动)延迟执行,则后续执行也会延迟。

你会更好地使用scheduleAtFixedRate.

或者,您可以尝试使用简单Thread的循环来重复执行任务。循环中的最后一步可以是休眠必要的时间,直到您想再次开始任务。假设没有一次循环迭代需要五分钟,这将消除累积延迟。

public void run() {
    long start = System.currentTimeMillis();
    while (shouldRun()) {
        doTask();
        long next = start + FIVE_MINUTES;
        try {
            Thread.sleep(next - System.currentTimeMillis());
            start = next;
        } catch (InterruptedException e) {
            . . .
        }
    }
}

这将在接下来的五分钟间隔开始每次迭代,并且不会由于运行时间doTask()或任何系统延迟而累积延迟。我没有查看来源,但我怀疑这与Timer.scheduleAtFixedRate.

于 2013-01-29T08:53:16.243 回答
1

为什么不使用任务调度程序或简单地在循环中使用睡眠命令,让线程睡眠 5 分钟然后继续。

另一种方法是使用Timer 类

于 2013-01-29T08:51:44.880 回答
0

我可能会使用ScheduleExecutorService.scheduleAtFixedRate,这是一种比使用 a 更现代的方法Timer,并且允许有多个工作线程,以防有许多任务被调度。

于 2013-01-29T09:02:48.923 回答