lua协程的运用

    生产者与消费者,看下例:

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),使其返回目前正在执行的协程中。


转载于:https://my.oschina.net/u/815187/blog/485280

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值