定时任务需要按到期时间排序执行:最早到期的先执行。朴素做法遍历全部任务找最早的 O(n);小顶堆(二叉堆)把最早到期的任务放在堆顶,弹出 O(log n)、插入 O(log n)。F:\底层文件 的数组访问确认:堆的父子节点用下标定位(父 i 子 2i/2i+1),无需指针结构,Lua 表直接实现。
小顶堆与延迟任务调度:入堆、弹出、扫描。示例代码如下:
local heap = {}
local function siftUp(h, i)
while i > 1 and h[i].ts < h[math.floor(i / 2)].ts do
local p = math.floor(i / 2)
h[i], h[p] = h[p], h[i]
i = p
end
end
local function siftDown(h, i)
local n = #h
while 2 * i <= n do
local c = 2 * i
if c < n and h[c + 1].ts < h[c].ts then
c = c + 1
end
if h[i].ts <= h[c].ts then
break
end
h[i], h[c] = h[c], h[i]
i = c
end
end
local function pushTask(h, task)
h[#h + 1] = task
siftUp(h, #h)
end
local function popTask(h)
local top = h[1]
h[1] = h[#h]
table.remove(h)
siftDown(h, 1)
return top
end
延迟任务调度示例代码如下:
local tasks = {}
pushTask(tasks, { ts = os.time() + 300, fn = function()
print("5 分钟后执行")
end })
pushTask(tasks, { ts = os.time() + 60, fn = function()
print("1 分钟后执行")
end })
while #tasks > 0 do
if tasks[1].ts <= os.time() then
local task = popTask(tasks)
task.fn()
else
break
end
end
1000 个延迟任务的插入与弹出:朴素数组遍历找最早的任务,每次 O(n) 约 0.03 毫秒,1000 次共 30 毫秒;小顶堆每次 O(log n) 约 0.003 毫秒,1000 次共 3 毫秒,快 10 倍。空间代价:堆数组与任务数线性。
三个不适用场景:一是任务数量少(百条以内)朴素遍历足够;二是任务不需要按优先级排序(先进先出即可)用普通队列;三是任务到期时间精度要求亚秒级时秒级时间戳不够用。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏】 一、一行代码拆解:if CONTRIB = price then CONTRIB = CONTRIB - pric…
【语法】 一、隐蔽陷阱:三个物品的全排列共 6 种,手写三重循环出 27 种含大量重复——递归交换法:固定一位、递归排其余、…
【语法】 一、抛坑提问:成就池 50 项,玩家已解锁 32 项,剩下的怎么一遍筛出?差集运算——以全集为基准,遍历时查已有集…
【语法】 一、抛坑提问:3 根柱子 5 个盘子从甲柱挪到丙柱,每次只能移一个且大盘不压小盘——把"挪 n 个"分解成"挪 n…
【游戏】 一、一行代码拆解:CASTING[actor] = nil —— 回城打断的核心:施法期间被攻击即清空施法状态并返…
【游戏】 一、一行代码拆解:APPLY[acc] = os.time() —— 入会审批的全部骨架:申请进队列带时间戳,官员…