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)