2

我正在使用 ScheduledThreadPoolExecutor 执行定期任务。执行必须是周期性的,而不是固定的延迟。

我遇到了以下问题:考虑一个任务的时间为 1 分钟。如果任务需要 5 分钟才能执行(例如,由于临时网络问题),错过的执行将在任务完成后立即排队并分派。有没有办法摆脱错过的累积处决?

我尝试使用 remove 方法,但它完全删除了任务,而不仅仅是特定的执行。

谢谢

4

3 回答 3

2

可能有更好的方法,但您可以让您的任务自行重新安排。这样,一次执行将始终在前一次执行完成后 1 分钟运行:

final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable yourTask = new Runnable() {

    @Override
    public void run() {
        //do your stuff
        scheduler.schedule(this, 1, TimeUnit.MINUTES);
    }
};
scheduler.schedule(yourTask, 1, TimeUnit.MINUTES);

编辑

如果您希望您的任务完全在 hh:mm:00(精确分钟)运行,您可以将代码替换为

long millisToNextMinute = 60000 - System.currentTimeMillis() % 60000;
scheduler.schedule(this, millisToNextMinute, TimeUnit.MILLISECONDS);
于 2012-08-08T12:51:52.940 回答
1

您可以将此逻辑构建到任务中。记录上次运行的任务。每次启动时,它都应该检查自上次运行以来是否经过了足够的时间。如果没有,那么它应该退出而不做任何工作。

于 2012-08-08T13:07:48.903 回答
0

CronScheduler中,有一些SkippingToLatest方法(请参阅Javadocs,“跳到最新运行”部分,专门为您处理此问题而设计:

Duration syncPeriod = Duration.ofMinutes(1);
CronScheduler cron = CronScheduler.create(syncPeriod);
cron.scheduleAtFixedRateSkippingToLatest(0, 1, TimeUnit.MINUTES, runTimeMillis -> {
    // Do your task
});
于 2020-01-29T14:22:39.357 回答