标签:
生产者与消费者,看下例:
local function producer() return coroutine.create( function(cookie) print("cookie = ",cookie) local t = {1,2,3} for i = 1,#t do cookie = coroutine.yield(t[i] + cookie) --cookie是consumer传回来的返回值 print(‘producer cookie‘,cookie) end print("******") end ) end function consumer(prod) local cookie = 10 while true do --cookie是producer coroutine.yield的返回值,cookie作为producer的返回值设置给cookie local running ,producer = coroutine.resume(prod, cookie) if running == false then return else print(‘running:‘,running,‘,producer:‘,producer,‘,cookie:‘,cookie) cookie = cookie*cookie end end end consumer(producer())
输出:
cookie = 10 running: true ,producer: 11 ,cookie: 10 producer cookie 100 running: true ,producer: 102 ,cookie: 100 producer cookie 10000 running: true ,producer: 10003 ,cookie: 10000 producer cookie 100000000 ****** running: true ,producer: nil ,cookie: 100000000
由输出我们可以知道,print("cookie = ",cookie)在producer协程第一次运行的时候被调用一次,接着进入for循环,刚进for循环的时候,producer就被挂起,这是yield会返回两个值给resume,第一个值如果为true则表示没有错误,否则则为发生了错误,第二个参数则是yield传入的参数,这里是:t[i] + cookie,第一次的时候,返回为true,11.接着由于consumer协程是会一直resume生产者(producer)协程的,知道返回非true为止。
上面的程序大致意思是:消费者刚刚开始的时候,想要10个饼干,然后他告诉生产者,生产者接收到消费者想要自己生产的饼干数量后开始生产,生产到比消费者想要的饼干数量加t[i](i为第几次生产)时,停止生产,并告诉消费者,我已经生产了的饼干数量。然后消费者开始使用这些饼干,然后消费者觉得饼干相当好吃,然后每次都以上一个的平方的数量让生产者生产饼干。在生产到第四次的时候,生产者不在生产饼干了,并通知消费者(可能是由于生产数量过大,而消费者不肯事先给订金而导致的)
我们也可以使用协程去替代回调函数。这是我在一个项目中遇到的一个问题,在战斗中,我们往往希望英雄在执行完某一步骤的时候,执行某一个方法,这时候大部分人都会选择回调函数来实现,但是在一个战斗系统中,会存在多次回调的情况,虽然回调函数也可以实现但是可读性就相对较差。比如我们想要英雄走到npc身边,然后咨询npc,接着npc回复,我们先用回调来实现一下:
hero.walk(function() hero.say(function() npc.say("...") end,"我帅吗?") end,npc)
接着我们使用协同程序来实现:
function dothing(func,...) --返回正在进行的线程,在主线程调用将返回nil local current = coroutine.running() func(function() coroutine.resume(current) end,...) coroutine.yield() end coroutine.create(function() dothing(hero.walk,npc) dothing(hero.say,"我帅吗?") npc.say("...") end) coroutine.resume(co)
一旦一个异步函数被调用,协程就会使用coroutine.yield()方法将该协程暂时悬挂起来,在相应的回调函数中加上coroutine.resume(current),使其返回目前正在执行的协程中。
标签:
原文地址:http://my.oschina.net/u/815187/blog/485280