Lua 协同程序(coroutine)
Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。
协同程序可以理解为一种特殊的线程,可以暂停和恢复其执行,从而允许非抢占式的多任务处理。
协同是非常强大的功能,但是用起来也很复杂。
基本语法
协同程序由 coroutine 模块提供支持。
使用协同程序,你可以在函数中使用 coroutine.create 创建一个新的协同程序对象,并使用 coroutine.resume 启动它的执行。协同程序可以通过调用 coroutine.yield 来主动暂停自己的执行,并将控制权交还给调用者。
| 方法 | 描述 |
|---|---|
| coroutine.create() | 创建 coroutine,返回 coroutine, 参数是一个函数,当和 resume 配合使用的时候就唤醒函数调用 |
| coroutine.resume() | 重启 coroutine,和 create 配合使用 |
| coroutine.yield() | 挂起 coroutine,将 coroutine 设置为挂起状态,这个和 resume 配合使用能有很多有用的效果 |
| coroutine.status() | 查看 coroutine 的状态 注:coroutine 的状态有三种:dead,suspended,running,具体什么时候有这样的状态请参考下面的程序 |
| coroutine.wrap() | 创建 coroutine,返回一个函数,一旦你调用这个函数,就进入 coroutine,和 create 功能重复 |
| coroutine.running() | 返回正在跑的 coroutine,一个 coroutine 就是一个线程,当使用running的时候,就是返回一个 coroutine 的线程号 |
以下实例演示了如何使用 Lua 协同程序:
function function1(param)
print(string.format("param:%s", param));
print("协同程序 function1 开始执行");
local value = coroutine.yield("暂停 function1 的执行");
print("协同程序 function1 恢复执行,传入的值为: " .. tostring(value))
print("协同程序 function1 结束执行");
return value.." return";
end
-- 创建协同程序
local retCoroutine = coroutine.create(function1);
-- 启动协同程序
local string1 = "I am a handsome programmer";
local status, result = coroutine.resume(retCoroutine, string1);
print(result) -- 输出: 暂停 foo 的执行
-- 恢复协同程序的执行,并传入一个值
local string2 = "I am a super handsome programmer";
local status, result = coroutine.resume(retCoroutine, string2);
print(status, result); -- 输出: 协同程序 foo 恢复执行,传入的值为:
以上实例中,我们定义了一个名为 foo 的函数作为协同程序。在函数中,我们使用 coroutine.yield 暂停了协同程序的执行,并返回了一个值
。在主程序中,我们使用 coroutine.create 创建了一个协同程序对象,并使用 coroutine.resume 启动了它的执行。
在第一次调用 coroutine.resume 后,协同程序执行到 coroutine.yield 处暂停,并将值返回给主程序。然后,我们再次调用 coroutine.resume,并传入一个值作为协同程序恢复执行时的参数。
执行以上代码输出结果为:
param:I am a handsome programmer
协同程序 function1 开始执行
暂停 function1 的执行
协同程序 function1 恢复执行,传入的值为: I am a super handsome programmer
协同程序 function1 结束执行
true I am a super handsome programmer return

需要注意的是,协同程序的状态可以通过 coroutine.status 函数获取,通过检查状态可以确定协同程序的执行情况(如运行中、已挂起、已结束等)。
以下实例演示了以上各个方法的用法:
local string1 = "I am a handsome programmer 1";
-- 创建了一个新的协同程序对象 co,其中协同程序函数打印传入的参数 param
local coroutine1 = coroutine.create(
function(param)
print(param);
end
);
-- 使用 coroutine.resume 启动协同程序 co 的执行,并传入参数 string1。协同程序开始执行,打印输出为 string1
coroutine.resume(coroutine1, string1); -- string1
-- 通过 coroutine.status 检查协同程序 co 的状态,输出为 dead,表示协同程序已经执行完毕
print(coroutine.status(coroutine1)); -- dead
print("----------");
-- 使用 coroutine.wrap 创建了一个协同程序包装器,将协同程序函数转换为一个可直接调用的函数对象
local coroutine2 = coroutine.wrap(
function(param)
print(param);
end
);
local string2 = "I am a handsome programmer 2";
coroutine2(string2);
print("----------");
-- 创建了另一个协同程序对象 coroutine3,其中的协同程序函数通过循环打印数字 1 到 10,
--在循环到 3 的时候输出当前协同程序的状态和正在运行的线程
local coroutine3 = coroutine.create(
function()
for i = 1, 32, 1 do
print(i);
print(coroutine.running()); --thread:XXXXXX
if (i == 16) then
print(coroutine.status(coroutine2)); --running
else
--coroutine.yield();
end
coroutine.yield();
end
end
)
-- 连续调用 coroutine.resume 启动协同程序 coroutine3 的执行
coroutine.resume(coroutine3); --1
coroutine.resume(coroutine3); --2
coroutine.resume(coroutine3); --3
-- 通过 coroutine.status 检查协同程序 co2 的状态,输出为 suspended,表示协同程序暂停执行
print(coroutine.status(coroutine3)); -- suspended
print(coroutine.running());
print("----------");
I am a handsome programmer 1
dead
----------
I am a handsome programmer 2
----------
1
thread: 00DE85A0
2
thread: 00DE85A0
3
thread: 00DE85A0
suspended
nil

7623

被折叠的 条评论
为什么被折叠?



