SystemTimer,TimerTaskList等源码分析
来源:互联网 发布:java dbcp连接池配置 编辑:程序博客网 时间:2024/06/05 13:35
一 SystemTimer
Kafka中定时器的实现,它在时间轮的基础上添加了执行到期任务,阻塞等待最近到期任务的功能
tickMs: Long 时间格
executorName: String 线程名字
wheelSize: Int 时间轮
startMs: Long 创建时间
taskExecutor:ExecutorService 固定线程池,由此线程执行定时到期任务
delayQueue:DelayQueue[TimerTaskList] 各个层级时间轮公用的DelayQueue,主要作用是阻塞推进时间轮指针的线程ExpiredOperationReaper,等待最近到期的任务
taskCounter:AtomicInteger 各个层级时间轮公用的任务个数计数器
timingWheel:TimingWheel 层级时间轮中对底层的时间轮
readWriteLock:ReentrantReadWriteLock 用来同步时间轮指针的currentTime修改后的读写锁
add 再添加过程中,如果发现任务已经到期,则将任务提交到taskExecutor执行;如果任务未到期,则调用TimerWheel.add提交到时间轮等待后期执行
defadd(timerTask:TimerTask): Unit = {
readLock.lock()
try {
// 将TimerTask封装成TimerTaskEntry,并计算到期时间
addTimerTaskEntry(newTimerTaskEntry(timerTask,timerTask.delayMs + SystemTime.hiResClockMs))
} finally {
readLock.unlock()
}
}
addTimerTaskEntry 向时间轮提交添加任务
private def addTimerTaskEntry(timerTaskEntry: TimerTaskEntry): Unit = { // 向时间轮提交添加任务失败,任务可能到期或者取消 if (!timingWheel.add(timerTaskEntry)) { // 如果不是取消,则提交给线程池 if (!timerTaskEntry.cancelled) taskExecutor.submit(timerTaskEntry.timerTask) }}
advanceClock 完成了时间轮指针的推进,同时对到期TimerTaskList的任务进行处理;如果TimerTaskList到期,但其中某些任务未到期 会将未到期的任务进行降级,添加到低层次的时间轮继续等待,如果任务到期了则提交到taskExecutor执行
def advanceClock(timeoutMs: Long): Boolean = { // 从队列取出第一个元素,如果不能立即取出,可以等待timeoutMs毫秒再取,还是没有取到返回空 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[timer] class TimerTaskList(taskCounter: AtomicInteger) extends Delayed { // TimerTaskList 是一个双向的循环列表 // root.next 指向下一个 // root.prev 指向前一个 // 创建一个TimerTaskEntry 节点,初始化next prev 都等于root,这是一个虚拟的TimerTaskEntry,并不存储任何任务 private[this] val root = new TimerTaskEntry(null, -1) root.next = root root.prev = root // 初始化该环形双向链表到期时间 private[this] val expiration = new AtomicLong(-1L) // 设置该环形双向链表的到期时间,如果里面的任务到期则交给线程执行,否则进行降级 // 如果到期时间改变返回true def setExpiration(expirationMs: Long): Boolean = { expiration.getAndSet(expirationMs) != expirationMs } // 获取该环形双向链表的到期时间 def getExpiration(): Long = { expiration.get() } // Apply the supplied function to each of tasks in this list def foreach(f: (TimerTask)=>Unit): Unit = { synchronized { // 获取下一个TimerTaskEntry节点 var entry = root.next // 如果TimerTaskEntry不等于root while (entry ne root) { // 获取下一个TimerTaskEntry下一个节点 val nextEntry = entry.next // 如果下一个entry没有被取消,调用函数f if (!entry.cancelled) f(entry.timerTask) entry = nextEntry } } } // Add a timer task entry to this list def add(timerTaskEntry: TimerTaskEntry): Unit = { var done = false while (!done) { // Remove the timer task entry if it is already in any other list // We do this outside of the sync block below to avoid deadlocking. // We may retry until timerTaskEntry.list becomes null. // 如果其他TimerTaskList也存在这个timerTaskEntry则删除它,避免死锁 timerTaskEntry.remove() synchronized { timerTaskEntry.synchronized { // timerTaskEntry所在的TimerTaskList如果为空 if (timerTaskEntry.list == null) { // put the timer task entry to the end of the list. (root.prev points to the tail entry) // 把当前timerTaskEntry放在队列尾部,并且前一个节点指向尾部的entry,下一个节点指向头部也 val tail = root.prev timerTaskEntry.next = root timerTaskEntry.prev = tail timerTaskEntry.list = this tail.next = timerTaskEntry root.prev = timerTaskEntry taskCounter.incrementAndGet()// 时间轮任务总数+1 done = true } } } } } // 从TimerTaskLKList删除指定的TimerTaskEntry def remove(timerTaskEntry: TimerTaskEntry): Unit = { synchronized { timerTaskEntry.synchronized { // 如果timerTaskEntry所在的TimerTaskList就是当前的TimerTaskList // 删除这个timerTaskEntry if (timerTaskEntry.list eq this) { timerTaskEntry.next.prev = timerTaskEntry.prev timerTaskEntry.prev.next = timerTaskEntry.next timerTaskEntry.next = null timerTaskEntry.prev = null timerTaskEntry.list = null taskCounter.decrementAndGet()// 时间轮任务总数-1 } } } } // 删除所有的task entry,并且每一个task entry应用函数f def flush(f: (TimerTaskEntry)=>Unit): Unit = { synchronized { var head = root.next while (head ne root) { remove(head) f(head) head = root.next } expiration.set(-1L) } } def getDelay(unit: TimeUnit): Long = { unit.convert(max(getExpiration - SystemTime.hiResClockMs, 0), TimeUnit.MILLISECONDS) } def compareTo(d: Delayed): Int = { val other = d.asInstanceOf[TimerTaskList] if(getExpiration < other.getExpiration) -1 else if(getExpiration > other.getExpiration) 1 else 0 }}
三 TimerTaskEntry源码分析
private[timer] class TimerTaskEntry(val timerTask: TimerTask, val expirationMs: Long) extends Ordered[TimerTaskEntry] { @volatile var list: TimerTaskList = null // TimerTaskEntry所在的TimerTaskList双向循环链表 var next: TimerTaskEntry = null // 下一个TimerTaskEntry var prev: TimerTaskEntry = null // 前一个TimerTaskEntry // 给当前TimerTaskEntry设置timer task if (timerTask != null) timerTask.setTimerTaskEntry(this) // 当前timer task entry是否取消了timer task def cancelled: Boolean = { timerTask.getTimerTaskEntry != this } def remove(): Unit = { var currentList = list // remove 被调用,其他的线程将会移动这个entry到一个其他的TimeTaskList,因此我们会重试直到TimeTaskList为空 // 删除这个entry可能会失败,因为TimeTaskList的值的改变 while (currentList != null) { // 从TimerTaskLKList删除指定的TimerTaskEntry currentList.remove(this) // TimerTaskLKList重新赋给currentList currentList = list } } override def compare(that: TimerTaskEntry): Int = { this.expirationMs compare that.expirationMs }}
四 TimerTask分析
trait TimerTask extends Runnable { val delayMs: Long // timestamp in millisecond private[this] var timerTaskEntry: TimerTaskEntry = null def cancel(): Unit = { synchronized { if (timerTaskEntry != null) timerTaskEntry.remove() timerTaskEntry = null } } // 即某一个timer task entry希望持有这个timer task,但是其他的timer task正持有它,则就把当前的这个timer task entry给删掉 private[timer] def setTimerTaskEntry(entry: TimerTaskEntry): Unit = { synchronized { // 如果某一个timer task被已经存在的timer task entry所持有,我们首先会删除这个timer task entry if (timerTaskEntry != null && timerTaskEntry != entry) timerTaskEntry.remove() timerTaskEntry = entry } } private[timer] def getTimerTaskEntry(): TimerTaskEntry = { timerTaskEntry }}
- SystemTimer,TimerTaskList等源码分析
- SystemTimer CurrentTimeMillis 时间缓存
- DropDownMenu仿美团等下拉菜单源码分析
- DropDownMenu仿美团等下拉菜单源码分析
- DropDownMenu仿美团等下拉菜单源码分析
- g723源码详细分析-12-更新内存与打包等
- 人工客服,二维码折扣,粉丝行为分析等源码分享
- hbase HTable之Put、delete、get等源码分析
- 源码分析 ItemTouchHelper手势的入口 (OnInterceptTouchEvent onLongPress等)
- ffmpeg源码分析及录制/压缩/上传视频等
- Wince Set SystemTimer by using .netcf
- 源码阅读与分析一:利用eclipse查看ssh等源码
- Heritrix1.14源码分析(5) 如何让Heritrix在Ecplise等IDE下编程启动
- Heritrix源码分析(五) 如何让Heritrix在Ecplise等IDE下编程启动
- Heritrix1.14源码分析(5) 如何让Heritrix在Ecplise等IDE下编程启动
- jQuery源码分析之blur focus focusin focusout load resize scroll unload click dblclick等方法
- ButterKnife -- 源码分析 -- 在‘编译期’间生成findViewById等代码
- HBase源码分析之MemStore的flush发起时机、判断条件等详情
- 学习笔记-正则表达式全部符号
- Java8-基础
- How to clone VM 使用cloudForms REST api
- sftp子系统申请已拒绝 请确保ssh连接的sftp子系统设置有效
- 条件,循环结构
- SystemTimer,TimerTaskList等源码分析
- DBSCAN聚类算法初探(五)
- Python中的str与unicode处理方法
- 【SLAM】之Point Cloud Library(PCL)简介与安装
- Java8-实践
- Kettle从Windows环境迁移到Linux运行报错
- Office Open XML 文档格式(转)
- python第三方模块的安装
- 面向对象程序设计的课上笔记