在java中安排单线程重复runnable,但如果之前的运行没有完成,则跳过当前运行

jon*_*rry 10 java

有时重复任务的持续时间比其周期长(在我的情况下,这可能一次发生几个小时).想象一个重复的任务需要7分钟才能运行并计划每10分钟运行一次,但有时需要15分钟才能连续几个小时运行.

Timer和ScheduledThreadPoolExecutor类都有一个scheduleAtFixedRate方法,通常用于此类功能.然而,两者都具有当他们落后时"试图赶上"的特征.换句话说,如果一个Timer落后于几次执行,它会建立一个工作队列,这个队列将持续工作,直到它回到可能发生的运行次数,如果没有任何任务耗时超过指定的期间.如果先前的运行未完成,我想通过跳过当前执行来避免此行为.

我有一个解决方案涉及搞乱池化执行器的afterExecution方法,重新计算延迟,并重新安排带有新延迟的runnable,但是想知道是否有更简单的方法,或者这个功能是否已经存在于某个公共库中.我知道调度具有固定的延迟而不是固定的时间段,但这对我不起作用,因为尝试在固定时间执行任务很重要.有没有比我的afterExecution解决方案更简单的选项?

Mar*_*ers 18

我想你想要的是长期运行的任务本身不能在ScheduledExecutorService本身运行,而是在后台线程中运行.然后固定速率任务将始终快速完成,因为它仅用于检查是否在后台启动实际任务(如果它仍在上次运行,则不会).

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
final Runnable actualTask = null;

executorService.scheduleAtFixedRate(new Runnable() {
    private final ExecutorService executor = Executors.newSingleThreadExecutor();
    private Future<?> lastExecution;
    @Override
    public void run() {
        if (lastExecution != null && !lastExecution.isDone()) {
            return;
        }
        lastExecution = executor.submit(actualTask);
    }
}, 10, 10, TimeUnit.MINUTES);
Run Code Online (Sandbox Code Playgroud)