游戏算法-时间轮算法,哈希大小时间轮Python

只需要二级,即可时间轮实现定时器

简单时间轮升级版,所有时间点的事件都有一个确定的槽位列表

达到当前时间点,执行槽位所有的事件即可

{小轮: {大轮: 槽位[]}}

小轮 = 定时时间 % wheel_ptr_max = 60  # 小轮的最大刻度

大轮 = 定时时间 / wheel_ptr_max = 60  # 大轮的最大刻度

self.ptr = 0  # 小轮当前刻度,增加清零
self.round = 0  # 大轮当前刻度,一直增加

时间复杂度

增:O(1)

减:约为O(1)

执行事件:约为O(1)

优点:快,理论延迟时间没有限制

缺点:占用资源

使用场合:定时器时间跨度大

 代码: simplewheel.py

# coding: utf-8
 
 
class SimpleWheel(object):
	wheel_ptr_max = 60  # 小轮大小
	scale = 1  # 一刻度时间单位
 
	def __init__(self):
		self.ptr = 0  # 小轮当前刻度(一级轮),增加清零
		self.round = 0  # 大轮当前刻度(二级轮),一直增加
		self.slots = {}  # {小轮: {大轮: [事件]}}
		self.unique_id = 0  # 自增唯一ID,用于删除节点
		
	def inc_unique_id(self):
		self.unique_id += 1
		return self.unique_id
		
	def on_tick(self):
		self.ptr += 1
		if self.ptr >= SimpleWheel.wheel_ptr_max:
			self.ptr = 0
			self.round += 1
		self.cal_timer()
	
	def cal_timer(self):
		lst = self.slots.get(self.ptr, {}).pop(self.round, [])
		for node in lst:
			print node.call()
		if self.ptr in self.slots:
			if not self.slots[self.ptr]:
				self.slots.pop(self.ptr, None)
	
	def start(self):
		# 开始时间轮
		self.cal_timer()
	
	def clear(self):
		# 清除
		self.slots.clear()
		self.round = 0
		self.ptr = 0
		self.unique_id = 0
		
	def add(self, func, sec):
		# 增加定时事件
        """
        计算例子:
        当前round: 1, 当前ptr:8时,wheel_ptr_max:10
        sec=5,计算round = 8 + 5 / 10 + 1 = 2, ptr =  8 + 5 % 10 = 3
        sec=20, 计算round = 8 + 20 / 10 + 1 = 3, ptr =  8 + 20 % 10 = 8
        """
		round, ptr = divmod(self.ptr + sec, SimpleWheel.wheel_ptr_max)
        round = round + self.round
		self.slots.setdefault(ptr, {})
		self.slots[ptr].setdefault(round, [])
		node = SlotNode(func, self.inc_unique_id())
		self.slots[ptr][round].append(node)
		print "add {0} sec event, round: {1}, ptr: {2}, node.uid: {3}".format(sec, round, ptr, node.uid)
		return round, ptr, node.uid
		
	def remove(self, key):
		# 删除定时事件
		round, ptr, uid = key
		lst = self.slots.get(ptr, {}).get(round, [])
		for i, node in enumerate(lst):
			if node.uid == uid:
				print "remove: {0}".format(lst[i].uid)
				del lst[i]
				break
	
	def is_emply(self):
		return not self.slots
		
 
# 事件节点
class SlotNode(object):
	def __init__(self, func, uid, *arg, **kwargs):
		self.uid = uid
		self.func = func
		self.args = arg
		self.kwargs = kwargs
 
	def call(self):
		return self.func(*self.args, **self.kwargs), "uid:", self.uid
 

测试代码: tset.py

# coding: utf-8
 
import threading
import simplewheel
import time
 
def func():
    return "func run, time: {0}".format(time.time() - start_time)
    
start_time = time.time()  # 调试用
 
 
wheel_ob = simplewheel.SimpleWheel()
 
def tick():
    wheel_ob.on_tick()
    handler = threading.Timer(simplewheel.SimpleWheel.scale, tick)
    if wheel_ob.is_emply():
        wheel_ob.clear()
    else:
        handler.start()


wheel_ob.add(func, 1)
wheel_ob.add(func, 2)
key = wheel_ob.add(func, 5)
wheel_ob.add(func, 15)
wheel_ob.add(func, 10)
wheel_ob.add(func, 20)
wheel_ob.remove(key)
wheel_ob.start()
handler = threading.Timer(simplewheel.SimpleWheel.scale, tick)
handler.start()


结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值