### Question:
RunnableWithDynamicPeriod implements Runnable { public void cancel(boolean b) { synchronized (cancelled) { cancelled.set(true); } } RunnableWithDynamicPeriod(Runnable lambda, List<Integer> periods, ScheduledExecutorService es); @Override void run(); void cancel(boolean b); void restart();  }### Answer:
@Test public void testCancel() throws Exception { executorService.submit(() -> System.out.println("warm up executor")); Thread.sleep(1000); List<Integer> periods = Arrays.asList(100,100,100,200); time = System.nanoTime(); AtomicInteger iTick = new AtomicInteger(0); AtomicInteger errorsCount = new AtomicInteger(0); RunnableWithDynamicPeriod r = new RunnableWithDynamicPeriod(() -> { long t1 = System.nanoTime(); long dt = (t1 - time) / 1000000; time = t1; long dt0 = periods.get(Math.min(iTick.get(), periods.size()-1)); System.out.println("tick: " + dt + "ms, must be " + dt0 + "ms"); if (!(Math.abs(dt0 - dt) < dt0/10)) errorsCount.incrementAndGet(); iTick.incrementAndGet(); }, periods, executorService); r.run(); System.out.println("wait for ticks"); Thread.sleep(2000); AtomicInteger ticksCount = new AtomicInteger(iTick.get()); System.out.println("now cancel"); r.cancel(true); Thread.sleep(2000); Assert.assertEquals(ticksCount.get(), iTick.get()); }