开发学院

您的位置:首页>教程>正文

教程正文

Lua 协程

Lua 协程

介绍

  协程是协作性的,它允许以受控的方式执行两种或两种以上的方法。有了协程,在任何给定的时间,只有一个协程运行,这个运行的协程在显式请求暂停时将暂停其执行。协程是非常强大的功能,但是用起来也很复杂。

  上述定义可能模糊不清。让我们假设有两种方法,一种主要的程序方法和一个协程。当我们使用resume函数调用协程时,它开始执行,当我们调用yield函数时,它将暂停执行。同样,协程可以从暂停的位置继续执行执行。这个过程可以持续到协程的执行结束。

协同程序中的可用功能

  下表列出了协程的可用函数及其相应的用法。

  coroutine.create(): 创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用

  coroutine.resume(): 重启coroutine,和create配合使用

  coroutine.yield() :挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果

  coroutine.status(): 查看coroutine的状态,注:coroutine的状态有三种:dead,suspend,running,具体什么时候有这样的状态请参考下面的程序

  coroutine.wrap(): 创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复

  coroutine.running(): 返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号

例子

  让我们看一段示例代码:

co = coroutine.create(function (value1,value2)
   local tempvar3 =10
   print("coroutine section 1", value1, value2, tempvar3)
   local tempvar1 = coroutine.yield(value1+1,value2+1)
   tempvar3 = tempvar3 + value1
   print("coroutine section 2",tempvar1 ,tempvar2, tempvar3)
   local tempvar1, tempvar2= coroutine.yield(value1+value2, value1-value2)
   tempvar3 = tempvar3 + value1
   print("coroutine section 3",tempvar1,tempvar2, tempvar3)
   return value2, "end"
end)

print("main", coroutine.resume(co, 3, 2))
print("main", coroutine.resume(co, 12,14))
print("main", coroutine.resume(co, 5, 6))
print("main", coroutine.resume(co, 10, 20))

  以上代码的执行结果为:

coroutine section 1	3	2	10
main	true	4	3
coroutine section 2	12	nil	13
main	true	5	1
coroutine section 3	5	6	16
main	true	2	end
main	false	cannot resume dead coroutine

以上例子做了什么?

  如前所述,我们使用resume启动操作和yield停止操作。此外,您可以看到,协程的恢复功能收到多个返回值。

  首先,我们创建一个协程,并将其分配给变量名称co,协程将两个变量作为其参数。

  当我们调用第一个resume函数时,值3和2保留在临时变量value1和value2中,直到协程的末尾。

  为了让您理解这一点,我们使用了一个tempvar3 ,它最初是10 ,它被协同程序的后续调用更新为13和16,因为value1在整个执行过程中保留为3。

  第一个coroutine.yield返回两个值4和3到resume函数,我们通过更新收率中的输入参数3和2得到。它还接收协程执行的true /false状态。

  关于协程的另一个问题是如何在上面的示例中处理下一个恢复调用的参数;您可以看到,coroutine.yield变量接收下一个调用参数,它提供了一种通过retentionship现有参数值进行新操作的强大方法。

  最后,一旦执行了协程中的所有语句,后续的调用将返回false,并且发送“cannot resume dead coroutine”语句作为响应。

其他的协程实例

  让我们看看一个简单的协程,它用产量函数和恢复函数的帮助从1到5返回一个数字。如果不可用,它将创建协程,否则将恢复现有协程。

function getNumber()
   local function getNumberHelper()
      co = coroutine.create(function ()
      coroutine.yield(1)
      coroutine.yield(2)
      coroutine.yield(3)
      coroutine.yield(4)
      coroutine.yield(5)
      end)
      return co
   end
   if(numberHelper) then
      status, number = coroutine.resume(numberHelper);
      if coroutine.status(numberHelper) == "dead" then
         numberHelper = getNumberHelper()
         status, number = coroutine.resume(numberHelper);
      end
      return number
   else
      numberHelper = getNumberHelper()
      status, number = coroutine.resume(numberHelper);
      return number
   end
end

for index = 1, 10 do
   print(index, getNumber())
end

  以上代码执行结果如下:

1	1
2	2
3	3
4	4
5	5
6	1
7	2
8	3
9	4
10	5

  通常我们会将协程与高级程序设计语言的线程进行比较,但是我们需要了解协程具有类似的线程的特性,但是它们每次只能执行一个线程,而不会并发执行。

  我们控制程序执行序列,以满足需要,暂时保留某些信息。使用全局变量和协同程序提供了更灵活的协同程序。