DelayedOperationPurgatory机制(二):SystemTimer

SystemTimer是kafka中定时器的实现,它在TimeWheel的基础上添加了执行到期任务、阻塞等待最近到期任务的功能

class SystemTimer(executorName: String,
                  tickMs: Long = 1,
                  wheelSize: Int = 20,
                  startMs: Long = System.currentTimeMillis) extends Timer {
  // timeout timer
  // JDK提供的固定线程数的线程池实现,由此线程执行到期任务
  private[this] val taskExecutor = Executors.newFixedThreadPool(1, new ThreadFactory() {
    def newThread(runnable: Runnable): Thread =
      Utils.newThread("executor-"+executorName, runnable, false)
  })
  // 各个层级的时间轮共用的DelayQueue队列,主要作用是阻塞推进时间表针的线程,等待最近到期任务到期
  private[this] val delayQueue = new DelayQueue[TimerTaskList]()
  // 各个层级时间轮共用的任务个数计时器
  private[this] val taskCounter = new AtomicInteger(0)
  // 层级时间轮中最底层的时间轮
  private[this] val timingWheel = new TimingWheel(
    tickMs = tickMs,
    wheelSize = wheelSize,
    startMs = startMs,
    taskCounter = taskCounter,
    delayQueue
  )

  // Locks used to protect data structures while ticking
  // 同步时间轮表针currentTime修改的读写锁
  private[this] val readWriteLock = new ReentrantReadWriteLock()
  private[this] val readLock = readWriteLock.readLock()
  private[this] val writeLock = readWriteLock.writeLock()
}

add方法添加过程中如果发现任务已经到期,则将任务提交到taskExecutor中执行,如果任务没有到期,就调用TimeWheel.add方法提交到时间轮中等到到期后执行。

  def add(timerTask: TimerTask): Unit = {
    readLock.lock()
    try {
        // 将TimerTask封装成TimerTaskEntry,并计算到期时间
      addTimerTaskEntry(new TimerTaskEntry(timerTask, timerTask.delayMs + System.currentTimeMillis()))
    } finally {
      readLock.unlock()
    }
  }
  
  private def addTimerTaskEntry(timerTaskEntry: TimerTaskEntry): Unit = {
      // 向时间轮提交添加任务失败,任务可能已经到期或者已经取消
    if (!timingWheel.add(timerTaskEntry)) {
      // Already expired or cancelled
      if (!timerTaskEntry.cancelled)// 将到期任务提交给taskExecutor执行
        taskExecutor.submit(timerTaskEntry.timerTask)
    }
  }

advanceClock完成了时间轮表针的推进。

  def advanceClock(timeoutMs: Long): Boolean = {
    var bucket = delayQueue.poll(timeoutMs, TimeUnit.MILLISECONDS)
    if (bucket != null) {
      writeLock.lock()
      try {
        while (bucket != null) {
            // 推动时间轮表针
          timingWheel.advanceClock(bucket.getExpiration())
          // 调用reinsert,尝试将bucket中的任务重新添加到时间轮中,此过程不一定是将任务提交给taskExecutor执行,对于未到期的任务只是从原来的时间轮降级继续等待
          bucket.flush(reinsert)
          bucket = delayQueue.poll()
        }
      } finally {
        writeLock.unlock()
      }
      true
    } else {
      false
    }
  }
  // timerTaskList重新提交到时间轮中
  private[this] val reinsert = (timerTaskEntry: TimerTaskEntry) => addTimerTaskEntry(timerTaskEntry)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值