@Override
  public void scheduleAtFixedRate(Runnable task, long initialDelay, long period) {
    ArgumentVerifier.assertNotNull(task, "task");
    ArgumentVerifier.assertNotNegative(initialDelay, "initialDelay");
    ArgumentVerifier.assertGreaterThanZero(period, "period");

    RecurringRateTask taskWrapper = new RecurringRateTask(task, initialDelay, period);
    addScheduled(taskWrapper);
  }
  @Override
  public void scheduleWithFixedDelay(Runnable task, long initialDelay, long recurringDelay) {
    ArgumentVerifier.assertNotNull(task, "task");
    ArgumentVerifier.assertNotNegative(initialDelay, "initialDelay");
    ArgumentVerifier.assertNotNegative(recurringDelay, "recurringDelay");

    RecurringDelayTask taskWrapper = new RecurringDelayTask(task, initialDelay, recurringDelay);
    addScheduled(taskWrapper);
  }
  /**
   * Constructs a new {@link AsyncCallListenerHelper} that will handle listeners with the provided
   * interface. The provided class MUST be an interface. All {@link #call()} invocations will occur
   * on the provided executor, but listeners may run on different executors if they are added with
   * their respective executors.
   *
   * @param listenerInterface Interface that listeners need to implement
   * @param executor {@link Executor} that {@link #call()} invocation will occur on
   */
  public AsyncCallListenerHelper(Class<? super T> listenerInterface, Executor executor) {
    super(listenerInterface);

    ArgumentVerifier.assertNotNull(executor, "executor");

    this.executor = executor;
  }