-- Lua中的携程 local function f(iNumber) print('function f start with '..iNumber) print('yield = '..coroutine.yield(iNumber + 1)) -- 包含yield就不能当作普通的函数进行调用了 print('function f end') end -- 创建一个协程 -- 创建的时候函数并没有开始执行 local cf = coroutine.create(f) local value = 0 -- 第一次从函数头开始执行,参数对应过去 -- 运行到yield为止,把yield的参数返回回来 -- yield类似于return -- 注意resume会多一个返回值,第一个返回值是Status,布尔类型 _,value = coroutine.resume(cf, 1) -- resume的返回值是yield的参数 print('r = '..value) -- 第二次执行,从上一次yield的地方开始 -- yield的返回值是本次resume的参数 coroutine.resume(cf, 10) -- 总结:resume和yield的关系像是一个环,头尾相接 -- 查看一个协程的状态 print(coroutine.status(cf)) -- 关闭一个协程 coroutine.close(cf) -- 另一种创建协程的方式 -- 好像调用的时候更方便 local wf = coroutine.wrap(f)
function f start with 1 r = 2 yield = 10 function f end dead
看一下使用多线程实现的「消费者&生产者模型」:多线程
使用协程实现的「消费者&生产者模型」是这样的:(可以对比一下区别)
-- 生产者&消费者模型 -- 生产者从一个位置读取数据 -- 生产者把数据交给消费者 -- 消费者处理数据:把数据放到新位置 local kDataSource = {} -- 数据源位置 local kDataTarget = {} -- 数据目标位置 -- 初始化一下源数据 for i=1,10 do table.insert(kDataSource, i*i) end -- 打印一个列表 local printList = function(kName, kList) print(kName..':') for i=1,#kList do print(i..' = '..kList[i]) end end printList('Source', kDataSource) local Send = function(kData) coroutine.yield(kData) end local Recv = function(kCoroutine) local bStatus, iValue = coroutine.resume(kCoroutine) if bStatus then return iValue end end -- 生产者,一直在生产数据 -- 生产者是一个协程 local Producer = function() for i=1,#kDataSource do local iValue = kDataSource[i] -- 生产出了数据 Send(iValue) end end local cProducer = coroutine.create(Producer) -- 消费者,一直在读取数据 local Consumer = function() while true do -- 一直尝试拿数据 local iValue = Recv(cProducer) if iValue then print('Recv Data = '..iValue) table.insert(kDataTarget, iValue) else print('Recv Done!') break end end end -- 消费者启动!直到生产者停止为止 Consumer() printList('Target', kDataTarget)