我正在使用 ScheduledThreadPoolExecutor 执行定期任务。执行必须是周期性的,而不是固定的延迟。
我遇到了以下问题:考虑一个任务的时间为 1 分钟。如果任务需要 5 分钟才能执行(例如,由于临时网络问题),错过的执行将在任务完成后立即排队并分派。有没有办法摆脱错过的累积处决?
我尝试使用 remove 方法,但它完全删除了任务,而不仅仅是特定的执行。
谢谢
我正在使用 ScheduledThreadPoolExecutor 执行定期任务。执行必须是周期性的,而不是固定的延迟。
我遇到了以下问题:考虑一个任务的时间为 1 分钟。如果任务需要 5 分钟才能执行(例如,由于临时网络问题),错过的执行将在任务完成后立即排队并分派。有没有办法摆脱错过的累积处决?
我尝试使用 remove 方法,但它完全删除了任务,而不仅仅是特定的执行。
谢谢
可能有更好的方法,但您可以让您的任务自行重新安排。这样,一次执行将始终在前一次执行完成后 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);
您可以将此逻辑构建到任务中。记录上次运行的任务。每次启动时,它都应该检查自上次运行以来是否经过了足够的时间。如果没有,那么它应该退出而不做任何工作。
在CronScheduler中,有一些SkippingToLatest
方法(请参阅Javadocs,“跳到最新运行”部分,专门为您处理此问题而设计:
Duration syncPeriod = Duration.ofMinutes(1);
CronScheduler cron = CronScheduler.create(syncPeriod);
cron.scheduleAtFixedRateSkippingToLatest(0, 1, TimeUnit.MINUTES, runTimeMillis -> {
// Do your task
});