cf框架提供内置的异步库cf
, 须要使用的时候咱们必须先导入API: local cf = require "cf"
.git
cf库内置了一些定时器方法, 这些方法为开发者提供了对时间事件的控制能力. cf.timeout
、cf.at
、cf.sleep
.github
cf.sleep
方法是一个阻塞
的定时器, 只有一个参数用来设置当前协程的休眠时间而且没有返回值. 此方法的行为(语义)取决于用户传入的参数:bash
number
类型的时候, 此方法将马上返回.cf.timeout
与cf.at
不会阻塞当前协程执行流程. 目前虽然暴露给开发者使用, 但真正的使用场景都仅限于在须要长链接业务内.框架
cf.timeout
与cf.at
都会返回一个timer
对象, 开发者能够在任什么时候候使用timer
对象的stop
方法中止定时器.dom
cf.timeout
与cf.at
的参数以下:异步
记住: cf.timeout
是一次性定时器, 回调函数被触发以后将会自动中止运行. 而cf.at
若是不使用stop
方法中止则会一直重复执行.函数
cf库提供了协程
的操做方法. 此协程
与Lua的原生协程有些许不一样, cf基于原生协程的基础上由框架管理生命周期.学习
须要异步执行一个函数可使用cf.fork
建立一个由cf调度的协程, 此方法会返回一个协程对象. 这个协程对象能够在它让出的时候用来主动唤醒.ui
cf.fork
方法的第一个参数func为function
类型, 从第二个参数开始的参数将会做为func的参数(通常状况下咱们会利用upvalue而不会显示传递参数).lua
须要暂停一个cf建立的协程可使用cf.wait
方法. 此方法没有参数, 但若是调用此方法的协程不是由cf
建立或不是main
协程则会出错.
cf.wakeup
方法用于唤醒由cf.wait
暂停的协程. cf.wait
方法的返回值由cf.wakeup
的行为决定, 当唤醒的是不存在的协程或唤醒正在执行的协程将会出错.
cf.wakeup
方法的第一个参数是一个协程对象, 协程对象以后的全部参数将会返回给cf.wait
进行接收.
须要获取当前协程对象的时候在这个协程执行流程之间使用cf.self
方法获取, cf.self
的做用与内置库coroutine.running
方法相同.
它返回一个协程对象与一个boolean值. 当协程对象为主(main
)协程时则bolean为true
, 不然为false
.
更多使用介绍请参考cf库的文档.
在本示例中! 咱们首先修改随机数生成器种子, 随机从0~1中间取一个随机数做为定时器的时间. 而后启动一个循环开始生成3个定时器.
-- main.lua local cf = require "cf" math.randomseed(os.time()) -- 设置随机数种子 for index = 1, 3 do local time = math.random() cf.timeout(time, function() print("第"..index.."个定时器的时间为:"..time) end) end
因为是随机生成的时间, 因此咱们在函数内部使用print方法将当前定时器的运行信息打印出来(第几个建立的定时器与定时器时间).
如今让咱们多运行几回来查看输出有什么不一样:
[candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin 第2个定时器的时间为:0.0029842634685338 第1个定时器的时间为:0.12212080322206 第3个定时器的时间为:0.38623028574511 [candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin 第1个定时器的时间为:0.10055952938274 第3个定时器的时间为:0.30804532766342 第2个定时器的时间为:0.32007071143016 [candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin 第3个定时器的时间为:0.083867806941271 第2个定时器的时间为:0.52678858255967 第1个定时器的时间为:0.74910803744569
能够看到, 每次的输出内容由于随机数产生的数值不一样而不一样.
一个定时器的启动与中止必然是相对应的. 下面这个示例展现了如何启动与
-- main.lua local cf = require "cf" local timer = cf.timeout(1, function () print("定时器触发") end) timer:stop()
在上述这段代码中, 咱们启动了一个1秒的一次性定时器而且获取了一个timer
的对象.
这个定时器会在超时
或主动中止
后中止运行, 即便屡次对同一个定时器对象调用stop
方法也是无害的操做.
若是不出意外的状况下, 开发者应该会看到这样的输出内容:
[candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin 定时器触发 [candy@MacBookPro:~/Documents/core_framework] $
若是您注释掉timer:stop()
这段代码, 将不会有任何内容输出.
cf的协程是任务执行的关键模块, 咱们利用协程能够达到异步任务的使用效果.
下面这个示例展现了如何使用协程来执行异步任务:
-- main.lua local cf = require "cf" print("主协程开始运行..") cf.fork(function () print("cf的协程开始运行..") end) print("主协程开始休眠..") cf.sleep(1) print("主协程结束休眠..")
首先咱们在主协程中建立了一个cf协程, 这个线程将在主协程睡眠(让出执行权)期间运行.
当主协程休眠结束后将继续运行. 因此, 它的输出应该是这样子的:
[candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin 主协程开始运行.. 主协程开始休眠.. cf的协程开始运行.. cf的协程结束运行.. 主协程结束休眠..
咱们来假设一个场景: 主协程建立一个协程执行循环计算任务, 当任务执行完毕后唤醒主协程而且将计算结果传递过来.
思路: 首先咱们利用前面学到的API获取主协程对象, 而后建立一个新的协程来执行计算. 计算完成以后将结果返回.
-- main.lua local cf = require "cf" local co = cf.self() print("主协程开始运行..") cf.fork(function () print("cf协程开始运行..") local result = 0 for index = 1, 100 do result = result + index end print("cf协程运行完毕, 返回结果而且唤醒主协程..") return cf.wakeup(co, result) end) print("主协程休眠等待计算完成..") local result = cf.wait() print("主协程休眠结束获取到结果为:"..result) print("主协程执行完毕..")
输出结果以下所示:
[candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin 主协程开始运行.. 主协程休眠等待计算完成.. cf协程开始运行.. cf协程运行完毕, 返回结果而且唤醒主协程.. 主协程休眠结束获取到结果为:5050 主协程执行完毕..
注意: 上述示例仅用于演示如何建立异步任务, 对CPU密集型运算毫无帮助. 真实使用场景通常是在IO密集型运算中使用.
首先咱们根据上述的API建立标准API
提供的循环定时器:
local cf = require "cf" local timer local index = 1 timer = cf.at(1, function () if index > 10 then print("定时器中止运行..") return timer:stop() end print("输出的数值为:", index) index = index + 1 end) -- timer:stop()
输出以下:
[candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin 输出的数值为: 1 输出的数值为: 2 输出的数值为: 3 输出的数值为: 4 输出的数值为: 5 输出的数值为: 6 输出的数值为: 7 输出的数值为: 8 输出的数值为: 9 输出的数值为: 10 定时器中止运行.. [candy@MacBookPro:~/Documents/core_framework] $
上述代码在每次循环定时器超时的时候都会执行回调函数输出当前自增数值, 最后在达到必定次数后自动中止运行. 这种形式的写法也是做者所推荐的写法.
固然, 咱们还有一种利用cf.sleep
的特殊
的定时器写法:
cf.fork(function () for index = 1, 10 do cf.sleep(1) print("输出的数值为:", index) end print("定时器中止运行..") end)
它的输出以下:
[candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin 输出的数值为: 1 输出的数值为: 2 输出的数值为: 3 输出的数值为: 4 输出的数值为: 5 输出的数值为: 6 输出的数值为: 7 输出的数值为: 8 输出的数值为: 9 输出的数值为: 10 定时器中止运行.. [candy@MacBookPro:~/Documents/core_framework] $
两种写法虽然行为上是一致, 可是两种不一样的定时器的内部实现行为倒是不同.
第一种定时器不管在可读性与可控性上来看都作的很是好. 第二种虽然能模拟第一种的行为, 可是在内部须要多建立一个协程来实现唤醒而且没法被外部中止.
并且必须使用第二种定时器的场景通常是不存在的, 可是为了演示仍是须要知会开发者尽可能不要编写毫无好处的代码 :).
下一章咱们将学习如何使用MQ库来完成消息队列的任务监听.