├── README.md ├── main.go └── timer ├── timingwheel.go └── linkedlist.go /README.md: -------------------------------------------------------------------------------- 1 | # timer 2 | Golang实现的基于时间轮算法的定时器! 3 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "runtime" 6 | "timer_server/timer" 7 | ) 8 | 9 | func callback1(args interface{}) { 10 | //只执行一次的事件 11 | if values, ok := args.([]string); ok { 12 | var str1 string = values[0] 13 | var str2 string = values[1] 14 | log.Println("callback1(" + str1 + "," + str2 + ")") 15 | } else { 16 | log.Println("callback1()") 17 | } 18 | } 19 | 20 | func callback2(args interface{}) { 21 | //每次在当前时间点之后5s插入一个定时器,这样就能形成每隔5秒调用一次callback2回调函数,可以用于周期性事件 22 | timer.SetTimer("callback2", 5, callback2, args) 23 | log.Println("callback2") 24 | } 25 | 26 | func main() { 27 | // cpu多核 28 | runtime.GOMAXPROCS(runtime.NumCPU()) 29 | // 定时器1,传入两个参数 30 | timer.SetTimer("callback1", 3, callback1, []string{"hello", "world"}) 31 | // 定时器2,不传参数 32 | timer.SetTimer("callback2", 6, callback2, nil) 33 | // 移除定时器 34 | //timer.Delete(timer.TimerMap["callback2"]) 35 | //运行计时器 36 | timer.Run() 37 | } 38 | -------------------------------------------------------------------------------- /timer/timingwheel.go: -------------------------------------------------------------------------------- 1 | package timer 2 | 3 | import ( 4 | "log" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | const wheel_cnt uint8 = 5 //时间轮数量5个 10 | var element_cnt_per_wheel = [wheel_cnt]uint32{256, 64, 64, 64, 64} //每个时间轮的槽(元素)数量。在 256+64+64+64+64 = 512 个槽中,表示的范围为 2^32 11 | var right_shift_per_wheel = [wheel_cnt]uint32{8, 6, 6, 6, 6} //当指针指向当前时间轮最后一位数,再走一位就需要向上进位。每个时间轮进位的时候,使用右移的方式,最快实现进位。这里是每个轮的进位二进制位数 12 | var base_per_wheel = [wheel_cnt]uint32{1, 256, 256 * 64, 256 * 64 * 64, 256 * 64 * 64 * 64} //记录每个时间轮指针当前指向的位置 13 | var mutex sync.Mutex //加锁 14 | var rwmutex sync.RWMutex 15 | var newest [wheel_cnt]uint32 //每个时间轮当前指针所指向的位置 16 | var timewheels [5][]*Node //定义5个时间轮 17 | var TimerMap map[string]*Node = make(map[string]*Node) //保存待执行的计时器,方便按链表节点指针地址直接删除定时器 18 | 19 | type Timer struct { 20 | Name string //定时器名称 21 | Inteval uint32 //时间间隔,即以插入该定时器的时间为起点,Inteval秒之后执行回调函数DoSomething()。例如进程插入该定时器的时间是2015-04-05 10:23:00,Inteval=5,则执行DoSomething()的时间就是2015-04-05 10:23:05。 22 | DoSomething func(interface{}) //自定义事件处理函数,需要触发的事件 23 | Args interface{} //上述函数的输入参数 24 | } 25 | 26 | func SetTimer(name string, inteval uint32, handler func(interface{}), args interface{}) { 27 | if inteval <= 0 { 28 | return 29 | } 30 | var bucket_no uint8 = 0 31 | var offset uint32 = inteval 32 | var left uint32 = inteval 33 | for offset >= element_cnt_per_wheel[bucket_no] { //偏移量大于当前时间轮容量,则需要向高位进位 34 | offset >>= right_shift_per_wheel[bucket_no] //计算高位的值。偏移量除以低位的进制。比如低位当前是256,则右移8个二进制位,就是除以256,得到的结果是高位的值。 35 | var tmp uint32 = 1 36 | if bucket_no == 0 { 37 | tmp = 0 38 | } 39 | left -= base_per_wheel[bucket_no] * (element_cnt_per_wheel[bucket_no] - newest[bucket_no] - tmp) 40 | bucket_no++ 41 | } 42 | if offset < 1 { 43 | return 44 | } 45 | if inteval < base_per_wheel[bucket_no]*offset { 46 | return 47 | } 48 | left -= base_per_wheel[bucket_no] * (offset - 1) 49 | pos := (newest[bucket_no] + offset) % element_cnt_per_wheel[bucket_no] //通过类似hash的方式,找到在时间轮上的插入位置 50 | 51 | var node Node 52 | node.SetData(Timer{name, left, handler, args}) 53 | 54 | rwmutex.RLock() 55 | TimerMap[name] = timewheels[bucket_no][pos].InsertHead(node) //插入定时器 56 | rwmutex.RUnlock() 57 | //fmt.Println("pos ", bucket_no, pos, tmp) 58 | } 59 | 60 | func step() { 61 | //var dolist list.List 62 | { 63 | rwmutex.RLock() 64 | //遍历所有桶 65 | var bucket_no uint8 = 0 66 | for bucket_no = 0; bucket_no < wheel_cnt; bucket_no++ { 67 | newest[bucket_no] = (newest[bucket_no] + 1) % element_cnt_per_wheel[bucket_no] //当前指针递增1 68 | //fmt.Println(newest) 69 | var head *Node = timewheels[bucket_no][newest[bucket_no]] //返回当前指针指向的槽位置的表头 70 | var firstElement *Node = head.Next() 71 | for firstElement != nil { //链表不为空 72 | if value, ok := firstElement.Data().(Timer); ok { //如果element里面确实存储了Timer类型的数值,那么ok返回true,否则返回false。 73 | inteval := value.Inteval 74 | doSomething := value.DoSomething 75 | args := value.Args 76 | if nil != doSomething { //有遇到函数为nil的情况,所以这里判断下非nil 77 | if 0 == bucket_no || 0 == inteval { 78 | //dolist.PushBack(value) //执行自定义处理函数 79 | go doSomething(args) 80 | } else { 81 | SetTimer(value.Name, inteval, doSomething, args) //重新插入计时器 82 | } 83 | } 84 | Delete(firstElement) //删除定时器 85 | } 86 | firstElement = head.Next() //重新定位到链表第一个元素头 87 | } 88 | if 0 != newest[bucket_no] { //指针不是0,还未转回到原点,跳出。如果回到原点,则说明转完了一圈,需要向高位进位1,则继续循环入高位步进一步。 89 | break 90 | } 91 | } 92 | rwmutex.RUnlock() 93 | } 94 | } 95 | 96 | func Run() { 97 | var i int = 0 98 | for { 99 | go step() 100 | i++ 101 | log.Printf("第%ds", i) 102 | //间隔时间inteval=1s 103 | time.Sleep(1 * time.Second) 104 | } 105 | } 106 | 107 | func init() { //初始化 108 | var bucket_no uint8 = 0 109 | for bucket_no = 0; bucket_no < wheel_cnt; bucket_no++ { 110 | var i uint32 = 0 111 | for ; i < element_cnt_per_wheel[bucket_no]; i++ { 112 | timewheels[bucket_no] = append(timewheels[bucket_no], new(Node)) 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /timer/linkedlist.go: -------------------------------------------------------------------------------- 1 | package timer 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | //定义节点 8 | type Node struct { 9 | data interface{} 10 | prev *Node 11 | next *Node 12 | } 13 | 14 | type LinkedList struct { 15 | head *Node 16 | last *Node 17 | length uint 18 | } 19 | 20 | func NewLinkedList() *LinkedList { 21 | var list *LinkedList = new(LinkedList) 22 | list.head = nil 23 | list.last = nil 24 | list.length = 0 25 | return list 26 | } 27 | 28 | /** 29 | * 获取表头 30 | */ 31 | func (this LinkedList) GetHead() *Node { 32 | return this.head 33 | } 34 | 35 | /** 36 | * 获取表尾 37 | */ 38 | func (this LinkedList) GetLast() *Node { 39 | return this.last 40 | } 41 | 42 | func (this LinkedList) Length() uint { 43 | return this.length 44 | } 45 | 46 | func (this *LinkedList) PushBack(node Node) *Node { 47 | node.next = nil 48 | if nil == this.head { //空表 49 | this.head = &node 50 | this.head.prev = nil 51 | this.last = this.head 52 | } else { 53 | node.prev = this.last 54 | this.last.next = &node 55 | this.last = this.last.next 56 | } 57 | fmt.Printf("insert %d %d\n", this.length, this.last.Data) 58 | this.length++ 59 | return this.last 60 | } 61 | 62 | func (this *LinkedList) erase(node *Node) { 63 | fmt.Println(node) 64 | if nil == node { 65 | return 66 | } else if nil == node.next && nil == node.next { 67 | return 68 | } 69 | if node == this.head && node == this.last { 70 | this.head = nil 71 | this.last = nil 72 | this.length = 0 73 | } else { 74 | if node == this.head { 75 | this.head = this.head.next 76 | if nil != this.head { 77 | this.head.prev = nil 78 | } 79 | } else if node == this.last { 80 | node.prev.next = nil 81 | this.last = node.prev 82 | } else { 83 | node.prev.next = node.next 84 | node.next.prev = node.prev 85 | } 86 | } 87 | this.length-- 88 | } 89 | 90 | func Delete(node *Node) { 91 | if nil == node { 92 | return 93 | } else if nil == node.prev { //该元素处于表头,不删除,默认表头不存元素 94 | return 95 | } else if nil == node.next { //该元素处于表尾 96 | node.prev.next = nil 97 | node.prev = nil 98 | } else { 99 | node.next.prev = node.prev 100 | node.prev.next = node.next 101 | node.prev = nil 102 | node.next = nil 103 | } 104 | } 105 | 106 | func (this *Node) InsertHead(node Node) *Node { //从表头插入 107 | if nil == this || nil != this.prev { //为空,或者不是表头(表头的prev为空) 108 | return nil 109 | } else { 110 | if nil != this.next { 111 | this.next.prev = &node 112 | node.next = this.next 113 | } 114 | this.next = &node 115 | node.prev = this 116 | } 117 | return &node 118 | } 119 | 120 | func (this *Node) Next() (node *Node) { 121 | return this.next 122 | } 123 | 124 | func (this *Node) Prev() (node *Node) { 125 | return this.prev 126 | } 127 | 128 | func (this *Node) Data() (data interface{}) { 129 | return this.data 130 | } 131 | 132 | func (this *Node) SetData(data interface{}) { 133 | this.data = data 134 | } 135 | 136 | /////test 137 | 138 | /*var n1 Node 139 | n1.data = 12345 140 | var n2 Node 141 | n2.data = 78459 142 | var n3 Node 143 | n3.data = 12 144 | 145 | 146 | var l1 = NewLinkedList() 147 | var pn1 *Node = l1.PushBack(n1) 148 | 149 | var l2 = NewLinkedList() 150 | var pn2 *Node = l2.PushBack(n2) 151 | l2.PushBack(n1) 152 | l2.PushBack(n3) 153 | 154 | 155 | fmt.Println("pn2",pn2) 156 | fmt.Println("pn1",pn1) 157 | //l2.erase(pn2) 158 | //l2.erase(pn1) 159 | 160 | 161 | for i:=l1.head; i!=nil; i = i.next { 162 | fmt.Println(i.data, l1.length) 163 | } 164 | for i:=l2.head; i!=nil; i = i.next { 165 | fmt.Println(i.data, l2.length) 166 | }*/ 167 | 168 | /* 169 | var head util.Node 170 | var head1 util.Node 171 | var n3 util.Node 172 | n3.SetData(11113) 173 | var n4 util.Node 174 | n4.SetData(11114) 175 | var n5 util.Node 176 | n5.SetData(22225) 177 | var n6 util.Node 178 | n6.SetData(33336) 179 | var n7 util.Node 180 | n7.SetData(77777) 181 | 182 | timerMap["h_n4"] = head.InsertHead(n4) 183 | head.InsertHead(n5) 184 | head.InsertHead(n6) 185 | 186 | timerMap["h1_n7"] = head1.InsertHead(n7) 187 | timerMap["h1_n4"] = head1.InsertHead(n4) 188 | head1.InsertHead(n5) 189 | head1.InsertHead(n3) 190 | 191 | fmt.Println(head) 192 | fmt.Println(n6) 193 | fmt.Println(n5) 194 | fmt.Println(n4) 195 | 196 | 197 | util.Delete(&head) 198 | util.Delete(timerMap["h_n4"]) 199 | 200 | for i:=head.Next(); i!=nil; i = i.Next() { 201 | fmt.Println(i.Data()) 202 | } 203 | 204 | util.Delete(timerMap["h1_n7"]) 205 | fmt.Println(n7) 206 | for i:=head1.Next(); i!=nil; i = i.Next() { 207 | fmt.Println(i.Data()) 208 | } 209 | */ 210 | --------------------------------------------------------------------------------