@Override public void run() { try { // Note: do not use Thread.interrupted() because it will clear the interrupt // status of the thread. while (!Thread.currentThread().isInterrupted()) { try { DelayedTask task = queue.take(); stats.incrementActiveTaskCount(); final long delay = clock.wallTime() - task.getNextExecutionTime(); stats.taskExecutionDelay().record(delay, TimeUnit.MILLISECONDS); stats.taskExecutionTime().record(() -> task.runAndReschedule(queue, stats)); } catch (InterruptedException e) { LOGGER.debug("task interrupted", e); break; } finally { stats.decrementActiveTaskCount(); } } } finally { startThreads(); } } }
boolean scheduleAgain = options.schedulingPolicy != Policy.RUN_ONCE; try { if (!isDone()) { task.run(); } finally { thread = null; if (scheduleAgain && !isDone()) { updateNextExecutionTime(stats.skipped()); queue.put(this); } else {
@Override public int compareTo(Delayed other) { final long d1 = getDelay(TimeUnit.MILLISECONDS); final long d2 = other.getDelay(TimeUnit.MILLISECONDS); return Long.compare(d1, d2); }
boolean scheduleAgain = options.schedulingPolicy != Policy.RUN_ONCE; try { if (!isDone()) { task.run(); } finally { thread = null; if (scheduleAgain && !isDone()) { updateNextExecutionTime(stats.skipped()); queue.put(this); } else {
@Test public void updateNextFixedRateSkip() { ManualClock clock = new ManualClock(); Registry registry = new DefaultRegistry(clock); Counter skipped = registry.counter("skipped"); Scheduler.Options options = new Scheduler.Options() .withFrequency(Scheduler.Policy.FIXED_RATE_SKIP_IF_LONG, Duration.ofSeconds(10)); clock.setWallTime(5437L); Scheduler.DelayedTask task = new Scheduler.DelayedTask(clock, options, () -> {}); Assertions.assertEquals(5437L, task.getNextExecutionTime()); Assertions.assertEquals(0L, skipped.count()); clock.setWallTime(12123L); task.updateNextExecutionTime(skipped); Assertions.assertEquals(15437L, task.getNextExecutionTime()); Assertions.assertEquals(0L, skipped.count()); clock.setWallTime(27000L); task.updateNextExecutionTime(skipped); Assertions.assertEquals(35437L, task.getNextExecutionTime()); Assertions.assertEquals(1L, skipped.count()); clock.setWallTime(57000L); task.updateNextExecutionTime(skipped); Assertions.assertEquals(65437L, task.getNextExecutionTime()); Assertions.assertEquals(3L, skipped.count()); }
/** * Schedule a repetitive task. * * @param options * Options for controlling the execution of the task. See {@link Options} * for more information. * @param task * Task to execute. * @return * Future that can be used for cancelling the current and future executions of * the task. There is no value associated with the task so the future is just for * checking if it is still running to stopping it from running in the future. */ public ScheduledFuture<?> schedule(Options options, Runnable task) { if (!started) { startThreads(); } DelayedTask t = new DelayedTask(clock, options, task); queue.put(t); return t; }
@Override public void run() { try { // Note: do not use Thread.interrupted() because it will clear the interrupt // status of the thread. while (!Thread.currentThread().isInterrupted()) { try { DelayedTask task = queue.take(); stats.incrementActiveTaskCount(); final long delay = clock.wallTime() - task.getNextExecutionTime(); stats.taskExecutionDelay().record(delay, TimeUnit.MILLISECONDS); stats.taskExecutionTime().record(() -> task.runAndReschedule(queue, stats)); } catch (InterruptedException e) { LOGGER.debug("task interrupted", e); break; } finally { stats.decrementActiveTaskCount(); } } } finally { startThreads(); } } }
/** * Schedule a repetitive task. * * @param options * Options for controlling the execution of the task. See {@link Options} * for more information. * @param task * Task to execute. * @return * Future that can be used for cancelling the current and future executions of * the task. There is no value associated with the task so the future is just for * checking if it is still running to stopping it from running in the future. */ public ScheduledFuture<?> schedule(Options options, Runnable task) { if (!started) { startThreads(); } DelayedTask t = new DelayedTask(clock, options, task); queue.put(t); return t; }
@Test public void updateNextFixedDelay() { ManualClock clock = new ManualClock(); Registry registry = new DefaultRegistry(clock); Counter skipped = registry.counter("skipped"); Scheduler.Options options = new Scheduler.Options() .withFrequency(Scheduler.Policy.FIXED_DELAY, Duration.ofSeconds(10)); clock.setWallTime(5437L); Scheduler.DelayedTask task = new Scheduler.DelayedTask(clock, options, () -> {}); Assertions.assertEquals(5437L, task.getNextExecutionTime()); Assertions.assertEquals(0L, skipped.count()); clock.setWallTime(12123L); task.updateNextExecutionTime(skipped); Assertions.assertEquals(22123L, task.getNextExecutionTime()); Assertions.assertEquals(0L, skipped.count()); clock.setWallTime(27000L); task.updateNextExecutionTime(skipped); Assertions.assertEquals(37000L, task.getNextExecutionTime()); Assertions.assertEquals(0L, skipped.count()); }
@Override public int compareTo(Delayed other) { final long d1 = getDelay(TimeUnit.MILLISECONDS); final long d2 = other.getDelay(TimeUnit.MILLISECONDS); return Long.compare(d1, d2); }