/**
   * Creates a new timer.
   *
   * @param threadFactory a {@link ThreadFactory} that creates a background {@link Thread} which is
   *     dedicated to {@link TimerTask} execution.
   * @param tickDuration the duration between tick
   * @param unit the time unit of the {@code tickDuration}
   * @param ticksPerWheel the size of the wheel
   */
  public HashedWheelTimer(
      ThreadFactory threadFactory, long tickDuration, TimeUnit unit, int ticksPerWheel) {

    if (threadFactory == null) {
      throw new NullPointerException("threadFactory");
    }
    if (unit == null) {
      throw new NullPointerException("unit");
    }
    if (tickDuration <= 0) {
      throw new IllegalArgumentException("tickDuration must be greater than 0: " + tickDuration);
    }
    if (ticksPerWheel <= 0) {
      throw new IllegalArgumentException("ticksPerWheel must be greater than 0: " + ticksPerWheel);
    }

    // Normalize ticksPerWheel to power of two and initialize the wheel.
    wheel = createWheel(ticksPerWheel);
    mask = wheel.length - 1;

    // Convert tickDuration to milliseconds.
    this.tickDuration = tickDuration = unit.toMillis(tickDuration);

    // Prevent overflow.
    if (tickDuration == Long.MAX_VALUE || tickDuration >= Long.MAX_VALUE / wheel.length) {
      throw new IllegalArgumentException("tickDuration is too long: " + tickDuration + ' ' + unit);
    }

    roundDuration = tickDuration * wheel.length; // 每一轮的时间

    workerThread = threadFactory.newThread(worker); // 创建一个线程

    // Misuse check
    misuseDetector.increase(); // 增加一个实例计数
  }
  /**
   * Creates a new instance.
   *
   * @param corePoolSize the maximum number of active threads
   * @param maxChannelMemorySize the maximum total size of the queued events per channel. Specify
   *     {@code 0} to disable.
   * @param maxTotalMemorySize the maximum total size of the queued events for this pool Specify
   *     {@code 0} to disable.
   * @param keepAliveTime the amount of time for an inactive thread to shut itself down
   * @param unit the {@link TimeUnit} of {@code keepAliveTime}
   * @param threadFactory the {@link ThreadFactory} of this pool
   * @param objectSizeEstimator the {@link ObjectSizeEstimator} of this pool
   */
  public MemoryAwareThreadPoolExecutor(
      int corePoolSize,
      long maxChannelMemorySize,
      long maxTotalMemorySize,
      long keepAliveTime,
      TimeUnit unit,
      ObjectSizeEstimator objectSizeEstimator,
      ThreadFactory threadFactory) {

    super(
        corePoolSize,
        corePoolSize,
        keepAliveTime,
        unit,
        QueueFactory.createQueue(Runnable.class),
        threadFactory,
        new NewThreadRunsPolicy());

    if (objectSizeEstimator == null) {
      throw new NullPointerException("objectSizeEstimator");
    }
    if (maxChannelMemorySize < 0) {
      throw new IllegalArgumentException("maxChannelMemorySize: " + maxChannelMemorySize);
    }
    if (maxTotalMemorySize < 0) {
      throw new IllegalArgumentException("maxTotalMemorySize: " + maxTotalMemorySize);
    }

    allowCoreThreadTimeOut(true);

    settings = new Settings(objectSizeEstimator, maxChannelMemorySize);

    if (maxTotalMemorySize == 0) {
      totalLimiter = null;
    } else {
      totalLimiter = new Limiter(maxTotalMemorySize);
    }

    // Misuse check
    misuseDetector.increase();
  }