Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。
1.线程可以同时运行,协同程序却需要彼此协作的运行。
2.在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。
协同程序有点类似与,在等待同一个线程锁的几个线程。
方法 | 描述 |
coroutine.create(func) | 创建coroutine,该方法只创建,如需唤醒coroutine需配合resume方法; 入参:是协程运行的函数; 返回:成功返回coroutine。 |
coroutine.resume(co, val1, ...) | 唤醒coroutine,和create配合使用; 入参:可任意输入,但是第一个入参必须是coroutine.create()的返回值。 1.如果是第一次唤醒,其余入参作为协程运行函数的入参。多余的参数被舍弃。 2.如果是唤醒调用yield()挂起的协程,其他输入参数将作为yield()的返回值。 除第一个入参外,如果入参个数少于yield()返回值个数,则执行失败,如果多于yield()返回 值个数,则多余的参数被舍弃,执行成功; 返回:成功返回true与yield()的入参。失败返回错误提示。 |
coroutine.yield(val1, ...) | 挂起coroutine,和resume配合使用能有很多有用的效果; 入参:可以任意输入,输入的入参将作为resume的返回值; 返回:resume()的入参作。 |
coroutine.status(co) | 获取coroutine的状态; 入参:coroutine.create()的返回值; 返回:返回coroutine的状态有四种:dead,suspend,running,normal。 |
coroutine.wrap(func) | 创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复; 入参:是协程运行的函数; 返回:成功返回一个函数。 |
coroutine.running() | 返回:正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号 |
1. coroutine.create(func)
创建一个主体函数为 func 的新协程。 func 必须是一个 Lua 的函数。 返回这个新协程,它是一个类型为 "thread" 的对象。不会启动该协程。
local co = coroutine.create(
function()
print("this is a coroutine")
return "coroutine return"
end)
print(co)
print(coroutine.resume(co))
输出:
2. coroutine.resume(co, val1, ...)与coroutine.yield(val1, ...)
coroutine.resume(co, val1, ...),开始或唤醒协程co的运行。
coroutine.yield(val1, ...),挂起正在调用的协程的执行。 传递给 yield 的参数都会转为 resume 的额外返回值。
local co = coroutine.create(
function (input)
print("input : "..input)
local param1, param2 ,param3 = coroutine.yield("yield1", "learning1")
print("param1 is : " .. param1)
print("param2 is : " .. param2)
print("param3 is : " .. param3)
local param4, param5 = coroutine.yield("yield2", "learning2")
print("param4 is : " .. param4)
print("param5 is : " .. param5)
-- return 也会将结果返回给 resume
return "coroutine return" , 1+2
end)
--第一次执行,将参数传给input
print("first resume",coroutine.resume(co, "coroutine function"))
print("this is main chunk")
--第二次执行,将参数作为yield的返回值,传给param1 param2 param3
print("second resume",coroutine.resume(co, "param1", "param2", "param3"))
--第三次执行,将参数作为yield的返回值,传给param4 param5 多余的param6被舍弃
print("third resume",coroutine.resume(co, "param4", "param5", "param6"))
输出:
分析:
3. coroutine.status(co)
以字符串形式返回协程 co 的状态:
local co
local co2 = coroutine.create(function() print("3."..coroutine.status(co)) end)
co = coroutine.create(
function ()
print("2."..coroutine.status(co))
coroutine.resume(co2)
coroutine.yield()
end)
print("1."..coroutine.status(co))
coroutine.resume(co)
print("4."..coroutine.status(co))
coroutine.resume(co)
print("5."..coroutine.status(co))
输出:
4. coroutine.wrap(func)
创建一个主体函数为 func 的新协程。func 必须是一个 Lua 的函数。返回一个函数,每次调用该函数都会延续该协程(不需要调用resume)。传给这个函数的参数都会作为 resume 的额外参数。和 resume 返回相同的值,只是没有第一个布尔量。
local wrap = coroutine.wrap(
function (input)
print("input : "..input)
local param1, param2 ,param3 = coroutine.yield("yield1", "learning1")
print("param1 is : " .. param1)
print("param2 is : " .. param2)
print("param3 is : " .. param3)
local param4, param5 = coroutine.yield("yield2", "learning2")
print("param4 is : " .. param4)
print("param5 is : " .. param5)
-- return 也会将结果返回给 resume
return "coroutine return" , 1+2
end)
--第一次执行,将参数传给input
print("first resume", wrap("coroutine function"))
print("this is main chunk")
--第二次执行,将参数作为yield的返回值,传给param1 param2 param3
print("second resume", wrap("param1", "param2", "param3"))
--第三次执行,将参数作为yield的返回值,传给param4 param5 多余的param6被舍弃
print("third resume", wrap("param4", "param5", "param6"))
输出:
注:coroutine.wrap不是保护模式运行,如果发生任何错误,抛出这个错误。如下
local wrap = coroutine.wrap(
function (input)
print("input : "..input)
local param1, param2 ,param3 = coroutine.yield("yield1", "learning1")
print("param1 is : " .. param1)
print("param2 is : " .. param2)
print("param3 is : " .. param3)
local param4 = coroutine.yield("yield2", "learning2")
print("param4 is : " .. param4)
print("param5 is : " .. param5)
-- return 也会将结果返回给 resume
return "coroutine return" , 1+2
end)
--第一次执行,将参数传给input
print("first resume", wrap("coroutine function"))
print("this is main chunk")
--第二次执行,将参数作为yield的返回值,传给param1 param2 param3
print("second resume", wrap("param1", "param2", "param3"))
--第三次执行,将参数作为yield的返回值,传给param4 param5 多余的param6被舍弃
print("third resume", wrap("param4", "param5", "param6"))
输出:
5. coroutine.running()
返回当前的协程,如果实在主线程,则返回nil
local co = coroutine.create(
function ()
print(coroutine.running())
end)
print(coroutine.running())
coroutine.resume(co)
print(co)
输出: