Lua语言入门 - Lua 协同程序(coroutine) (一)

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值