go:基于时间轮定时器方案
/*
* http://blog.csdn.net/yueguanghaidao/article/details/46290539
* 修改内容:为定时器增加类型和参数属性,修改回调函数类型
*/
package timer
import (
"container/list"
"fmt"
"sync"
"time"
)
//referer https://github.com/cloudwu/skynet/blob/master/skynet-src/skynet_timer.c
const (
TIME_NEAR_SHIFT = 8
TIME_NEAR = 1 << TIME_NEAR_SHIFT
TIME_LEVEL_SHIFT = 6
TIME_LEVEL = 1 << TIME_LEVEL_SHIFT
TIME_NEAR_MASK = TIME_NEAR - 1
TIME_LEVEL_MASK = TIME_LEVEL - 1
)
type Timer struct {
near [TIME_NEAR]*list.List
t [4][TIME_LEVEL]*list.List
sync.Mutex
time uint32
tick time.Duration
quit chan struct{}
}
type Node struct {
expire uint32
/*
* 增加定时器类型和定时器参数
*/
t int
arg string
f func(int, string)
}
var T *Timer
func init() {
timer := New(time.Millisecond * 10)
T = timer
fmt.Println("start timer server...")
go T.Start()
}
func (n *Node) String() string {
return fmt.Sprintf("Node:expire,%d,t:%d,arg:%s", n.expire, n.t, n.arg)
}
func New(d time.Duration) *Timer {
t := new(Timer)
t.time = 0
t.tick = d
t.quit = make(chan struct{})
var i, j int
for i = 0; i < TIME_NEAR; i++ {
t.near[i] = list.New()
}
for i = 0; i < 4; i++ {
for j = 0; j < TIME_LEVEL; j++ {
t.t[i][j] = list.New()
}
}
return t
}
func (t *Timer) addNode(n *Node) {
expire := n.expire
current := t.time
if (expire | TIME_NEAR_MASK) == (current | TIME_NEAR_MASK) {
t.near[expire&TIME_NEAR_MASK].PushBack(n)
} else {
var i uint32
var mask uint32 = TIME_NEAR << TIME_LEVEL_SHIFT
for i = 0; i < 3; i++ {
if (expire | (mask - 1)) == (current | (mask - 1)) {
break
}
mask <<= TIME_LEVEL_SHIFT
}
t.t[i][(expire>>(TIME_NEAR_SHIFT+i*TIME_LEVEL_SHIFT))&TIME_LEVEL_MASK].PushBack(n)
}
}
func (t *Timer) NewTimer(d time.Duration, f func(int, string), tp int, arg string) *Node {
n := new(Node)
n.f = f
n.t = tp
n.arg = arg
t.Lock()
n.expire = uint32(d/t.tick) + t.time
t.addNode(n)
t.Unlock()
return n
}
func (t *Timer) String() string {
return fmt.Sprintf("Timer:time:%d, tick:%s", t.time, t.tick)
}
func dispatchList(front *list.Element) {
for e := front; e != nil; e = e.Next() {
node := e.Value.(*Node)
go node.f(node.t, node.arg)
}
}
func (t *Timer) moveList(level, idx int) {
vec := t.t[level][idx]
front := vec.Front()
vec.Init()
for e := front; e != nil; e = e.Next() {
node := e.Value.(*Node)
t.addNode(node)
}
}
func (t *Timer) shift() {
t.Lock()
var mask uint32 = TIME_NEAR
t.time++
ct := t.time
if ct == 0 {
t.moveList(3, 0)
} else {
time := ct >> TIME_NEAR_SHIFT
var i int = 0
for (ct & (mask - 1)) == 0 {
idx := int(time & TIME_LEVEL_MASK)
if idx != 0 {
t.moveList(i, idx)
break
}
mask <<= TIME_LEVEL_SHIFT
time >>= TIME_LEVEL_SHIFT
i++
}
}
t.Unlock()
}
func (t *Timer) execute() {
t.Lock()
idx := t.time & TIME_NEAR_MASK
vec := t.near[idx]
if vec.Len() > 0 {
front := vec.Front()
vec.Init()
t.Unlock()
// dispatch_list don't need lock
dispatchList(front)
return
}
t.Unlock()
}
func (t *Timer) update() {
// try to dispatch timeout 0 (rare condition)
t.execute()
// shift time first, and then dispatch timer message
t.shift()
t.execute()
}
func (t *Timer) Start() {
tick := time.NewTicker(t.tick)
defer tick.Stop()
for {
select {
case <-tick.C:
t.update()
case <-t.quit:
return
}
}
}
func (t *Timer) Stop() {
close(t.quit)
}
go:基于时间轮定时器方案的更多相关文章
- 经典多级时间轮定时器(C语言版)
经典多级时间轮定时器(C语言版) 文章目录 经典多级时间轮定时器(C语言版) 1. 序言 2. 多级时间轮实现框架 2.1 多级时间轮对象 2.2 时间轮对象 2.3 定时任务对象 2.4 双向链表 ...
- 记录——时间轮定时器(lua 实现)
很长一段时间里,我错误的认识了定时器.无意中,我发现了“时间轮”这个名词,让我对定时器有了新的看法. 我错误的认为,定时器只需要一个 tick 队列,按指定的时间周期遍历队列,检查 tick 倒计时满 ...
- [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用
[从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用 目录 [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用 0x00 摘要 0x01 业务领域 1.1 应用场景 0x02 定 ...
- SpringBoot定时任务 - 经典定时任务设计:时间轮(Timing Wheel)案例和原理
Timer和ScheduledExecutorService是JDK内置的定时任务方案,而业内还有一个经典的定时任务的设计叫时间轮(Timing Wheel), Netty内部基于时间轮实现了一个Ha ...
- Kafka中时间轮分析与Java实现
在Kafka中应用了大量的延迟操作但在Kafka中 并没用使用JDK自带的Timer或是DelayQueue用于延迟操作,而是使用自己开发的DelayedOperationPurgatory组件用于管 ...
- Kafka解惑之时间轮 (TimingWheel)
Kafka中存在大量的延迟操作,比如延迟生产.延迟拉取以及延迟删除等.Kafka并没有使用JDK自带的Timer或者DelayQueue来实现延迟的功能,而是基于时间轮自定义了一个用于实现延迟功能的定 ...
- kafka时间轮的原理(一)
概述 早就想写关于kafka时间轮的随笔了,奈何时间不够,技术感觉理解不到位,现在把我之前学习到的进行整理一下,以便于以后并不会忘却.kafka时间轮是一个时间延时调度的工具,学习它可以掌握更加灵活先 ...
- .Net之时间轮算法(终极版)定时任务
TimeWheelDemo 一个基于时间轮原理的定时器 对时间轮的理解 其实我是有一篇文章(.Net 之时间轮算法(终极版))针对时间轮的理论理解的,但是,我想,为啥我看完时间轮原理后,会采用这样的方 ...
- .Net 之时间轮算法(终极版)
关于时间轮算法的起始 我也认真的看了时间轮算法相关,大致都是如下的一个图 个人认为的问题 大部分文章在解释这个为何用时间轮的时候都再说 假设我们现在有一个很大的数组,专门用于存放延时任务.它的精度达到 ...
随机推荐
- 循环中点击单个事件(巧用this,指向当前对象)
<em id='show' value="<?php echo $member['phone']; ?>" class="sui">&l ...
- pip安装报错处理+PyPi源切换教程
一.pip安装出错类型 1.1 pip版本过旧导致不能安装 报错提示: You are using pip version 9.0.3, however version 10.0.1 is avail ...
- eclipse安装springboot插件
1.工具栏->Help->Eclise Marketplace打开应用市场 2.在应用市场中搜索sts,选择Spring Tools 4紧张安装 3.按提示进行安装
- 0-MAVEN SETTING
localRepository : 表示本地库的保存位置,也就是maven主要的jar包保存位置,默认在${user.dir}/.m2/repository,如果需要另外设置,就换成其他的路径 Ser ...
- Win10系列:UWP界面布局基础12
画刷 画刷(Brush)用于为图形元素填充颜色.在XAML中,画刷有许多属性,其中较常使用的是Fill属性和Stroke属性,Fill用于填充图形的背景色,而Stroke用于设置图形的线条颜色. 在实 ...
- java 一些容易忽视的小点-控制语句
随机数 .Math.random()该方法用于产生一个0到1区间的double类型的随机数,但是不包括1 if-else循环语句 如果if语句不写{},则只能作用于后面的第一条语句 switch语句 ...
- Spring Boot + Spring Cloud 实现权限管理系统 (集成 Shiro 框架)
Apache Shiro 优势特点 它是一个功能强大.灵活的,优秀开源的安全框架. 它可以处理身份验证.授权.企业会话管理和加密. 它易于使用和理解,相比Spring Security入门门槛低. 主 ...
- 计算机基础及发展 part2
一.为什么有操作系统? 一台电脑的基本设备是硬件,诸如:CPU.I/O设备.主存.显示器.打印机等等. 如果软件编程者需要参考如此多的硬件参数来进行编程的话,基本上就不可能再书写代码了. 那么为了有效 ...
- 安装连接mysql8时候遇到的问题以及解决(转)
官网下载mysql8的安装包: https://dev.mysql.com/downloads/ 下一步安装即可. mysql8增加了传说中的安全性校验 遇到的几个问题: 1.natcat连接不上.参 ...
- 8.Python爬虫实战一之爬取糗事百科段子
大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧.那么这次为大家带来,Python爬取糗事百科的小段子的例子. 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把 ...