13.协同程序
13.1 知识点
协程的创建
- 创建协程有两种方法:
coroutine.create和coroutine.wrap。 coroutine.create创建出来的是thread类型。coroutine.wrap创建出来的是function类型。- 这里说的
thread是 Lua 里的协程类型,不是操作系统线程,基础阶段不要和多线程混在一起理解。
线程型 coroutine.create(函数变量)
myFunction1 = function()
print("我是myFunction1")
end
-- coroutine.create(函数变量) 会返回 thread 类型的变量,比较常用
myCoroutine1 = coroutine.create(myFunction1)
print(myCoroutine1) -- thread: 00B5EA90
print(type(myCoroutine1)) -- thread
函数型 coroutine.wrap(函数变量)
-- coroutine.wrap(函数变量) 会返回 function 类型的变量
myCoroutine2 = coroutine.wrap(function()
print("我是myFunction2")
end) -- 可以传入时声明函数
print(myCoroutine2) -- function: 00DBE058
print(type(myCoroutine2)) -- function
协程的执行
- 执行协程有两种方式:
coroutine.create创建出来的协程,用coroutine.resume执行。coroutine.wrap创建出来的协程,像普通函数一样用()执行。
线程型 coroutine.resume(协程变量)
-- coroutine.resume(协程变量)
-- 协程变量要是 thread 类型
coroutine.resume(myCoroutine1) -- 我是myFunction1
函数型 协程变量()
-- 协程变量()
-- 协程变量要是 function 类型
myCoroutine2() -- 我是myFunction2
协程的挂起和分步执行
- 协程真正有用的地方,是可以在函数内部用
coroutine.yield主动挂起。 - 下次再执行这个协程时,会从上次
yield的位置继续往下跑。 - 可以先把它理解成:函数执行到一半先停住,下一次再从停住的位置继续执行。
- 基础阶段先掌握
yield和resume / wrap的配合即可,不展开协程调度器和工程清理问题。
挂起线程型协程 coroutine.yield(返回值1, …返回值n) 和 coroutine.resume(协程变量)
-- 在函数中使用 coroutine.yield(返回值1, 返回值2, ...返回值n)
myFunction3 = function()
local i = 1
while true do
for j = 1, 3 do
print("myFunction3中打印值" .. " i:" .. i .. " j:" .. j)
coroutine.yield(i, j)
end
i = i + 1
end
end
- 使用
coroutine.create(函数变量)创建线程型协程。 - 使用
coroutine.resume(协程变量)分步执行函数,并得到当前yield返回值。 resume的第一个返回值表示这次协程是否执行成功。- 后面的返回值,才是
coroutine.yield()里传出来的值。
myCoroutine3 = coroutine.create(myFunction3) -- 线程型协程
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
-- myFunction3中打印值 i:1 j:1
-- 线程型协程的返回值: true 1 1
-- myFunction3中打印值 i:1 j:2
-- 线程型协程的返回值: true 1 2
-- myFunction3中打印值 i:1 j:3
-- 线程型协程的返回值: true 1 3
-- myFunction3中打印值 i:2 j:1
-- 线程型协程的返回值: true 2 1
-- myFunction3中打印值 i:2 j:2
-- 线程型协程的返回值: true 2 2
-- myFunction3中打印值 i:2 j:3
-- 线程型协程的返回值: true 2 3
-- myFunction3中打印值 i:3 j:1
-- 线程型协程的返回值: true 3 1
-- myFunction3中打印值 i:3 j:2
-- 线程型协程的返回值: true 3 2
-- myFunction3中打印值 i:3 j:3
-- 线程型协程的返回值: true 3 3
-- myFunction3中打印值 i:4 j:1
-- 线程型协程的返回值: true 4 1
-- myFunction3中打印值 i:4 j:2
-- 线程型协程的返回值: true 4 2
挂起函数型协程 coroutine.yield(返回值1, …返回值n) 和 协程变量()
-- 在函数中使用 coroutine.yield(返回值1, 返回值2, ...返回值n)
myFunction4 = function()
local i = 1
while true do
for j = 1, 3 do
print("myFunction4中打印值" .. " i:" .. i .. " j:" .. j)
coroutine.yield(i, j)
end
i = i + 1
end
end
- 使用
coroutine.wrap(函数变量)创建函数型协程。 - 使用
协程变量()分步执行函数,并得到当前yield返回值。 - 和
resume不同,wrap返回的函数执行时,没有第一个“是否执行成功”的返回值。 - 它会直接返回
coroutine.yield()里传出来的值。
myCoroutine4 = coroutine.wrap(myFunction4) -- 函数型协程
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
-- myFunction4中打印值 i:1 j:1
-- 函数型协程的返回值: 1 1
-- myFunction4中打印值 i:1 j:2
-- 函数型协程的返回值: 1 2
-- myFunction4中打印值 i:1 j:3
-- 函数型协程的返回值: 1 3
-- myFunction4中打印值 i:2 j:1
-- 函数型协程的返回值: 2 1
-- myFunction4中打印值 i:2 j:2
-- 函数型协程的返回值: 2 2
-- myFunction4中打印值 i:2 j:3
-- 函数型协程的返回值: 2 3
-- myFunction4中打印值 i:3 j:1
-- 函数型协程的返回值: 3 1
-- myFunction4中打印值 i:3 j:2
-- 函数型协程的返回值: 3 2
-- myFunction4中打印值 i:3 j:3
-- 函数型协程的返回值: 3 3
-- myFunction4中打印值 i:4 j:1
-- 函数型协程的返回值: 4 1
-- myFunction4中打印值 i:4 j:2
-- 函数型协程的返回值: 4 2
协程的状态 coroutine.status(协程变量)
coroutine.status(协程变量)可以得到当前协程的状态。- 这里的协程变量必须是
coroutine.create创建出来的thread类型。 coroutine.wrap返回的是function,不能直接传给coroutine.status。- 协程常见状态有:
suspended:暂停,刚创建但还没执行,或者执行到yield后停住。running:正在运行。dead:已经执行结束。normal:协程恢复了另一个协程时可能出现,基础阶段先知道有这个状态即可。
print(coroutine.status(myCoroutine1)) -- dead,因为 myCoroutine1 已经执行完毕
-- print(coroutine.status(myCoroutine2)) -- 报错,因为 myCoroutine2 是 wrap 返回的函数型协程
print(coroutine.status(myCoroutine3)) -- suspended,因为 myCoroutine3 执行到 yield 后暂停
-- print(coroutine.status(myCoroutine4)) -- 报错,因为 myCoroutine4 是 wrap 返回的函数型协程
myFunction5 = function()
print("我是myFunction5")
-- 当前协程正在运行中,所以这里打印 running
print(coroutine.status(myCoroutine5))
coroutine.yield()
end
myCoroutine5 = coroutine.create(myFunction5) -- 线程型协程
coroutine.resume(myCoroutine5) -- 在函数中打印 running
13.2 知识点代码
Lesson13_协同程序.lua
print("**********协同程序************")
print("**********知识点一 协程的创建************")
-- 创建协程有两种方法:create 和 wrap
-- create 创建 thread 类型的协程变量
-- wrap 创建 function 类型的协程变量
-- 这里的 thread 是 Lua 里的协程类型,不是操作系统线程
-- 线程型
myFunction1 = function()
print("我是myFunction1")
end
-- coroutine.create(函数变量) 会返回 thread 类型的变量,比较常用
myCoroutine1 = coroutine.create(myFunction1)
print(myCoroutine1) -- thread: 00B5EA90
print(type(myCoroutine1)) -- thread
-- 函数型
-- coroutine.wrap(函数变量) 会返回 function 类型的变量
myCoroutine2 = coroutine.wrap(function()
print("我是myFunction2")
end) -- 可以传入时声明函数
print(myCoroutine2) -- function: 00DBE058
print(type(myCoroutine2)) -- function
print("**********知识点二 协程的执行************")
-- 执行协程有两种方式:
-- coroutine.create 创建出来的协程,用 coroutine.resume 执行
-- coroutine.wrap 创建出来的协程,像普通函数一样用 () 执行
-- coroutine.resume(协程变量),协程变量要是 thread 类型
coroutine.resume(myCoroutine1) -- 我是myFunction1
-- 协程变量(),协程变量要是 function 类型
myCoroutine2() -- 我是myFunction2
print("**********知识点三 协程的挂起************")
-- 协程真正有用的地方,是可以在函数内部用 coroutine.yield 主动挂起
-- 下次再执行这个协程时,会从上次 yield 的位置继续往下跑
-- 可以先理解成:函数执行到一半先停住,下一次再从停住的位置继续执行
-- 挂起线程型协程
-- 在函数中使用 coroutine.yield(返回值1, 返回值2, ...返回值n)
myFunction3 = function()
local i = 1
while true do
for j = 1, 3 do
print("myFunction3中打印值" .. " i:" .. i .. " j:" .. j)
coroutine.yield(i, j)
end
i = i + 1
end
end
-- 使用 coroutine.create(函数变量) 创建 thread 类型协程
-- 使用 coroutine.resume(协程变量) 分步执行函数,并得到当前返回值
-- resume 的第一个返回值表示这次协程是否执行成功
-- 后面的返回值才是 coroutine.yield() 里传出来的值
myCoroutine3 = coroutine.create(myFunction3)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
isCoroutineSuccessLaunch, tempI, tempJ = coroutine.resume(myCoroutine3)
print("线程型协程的返回值:", isCoroutineSuccessLaunch, tempI, tempJ)
-- myFunction3中打印值 i:1 j:1
-- 线程型协程的返回值: true 1 1
-- myFunction3中打印值 i:1 j:2
-- 线程型协程的返回值: true 1 2
-- myFunction3中打印值 i:1 j:3
-- 线程型协程的返回值: true 1 3
-- myFunction3中打印值 i:2 j:1
-- 线程型协程的返回值: true 2 1
-- myFunction3中打印值 i:2 j:2
-- 线程型协程的返回值: true 2 2
-- myFunction3中打印值 i:2 j:3
-- 线程型协程的返回值: true 2 3
-- myFunction3中打印值 i:3 j:1
-- 线程型协程的返回值: true 3 1
-- myFunction3中打印值 i:3 j:2
-- 线程型协程的返回值: true 3 2
-- myFunction3中打印值 i:3 j:3
-- 线程型协程的返回值: true 3 3
-- myFunction3中打印值 i:4 j:1
-- 线程型协程的返回值: true 4 1
-- myFunction3中打印值 i:4 j:2
-- 线程型协程的返回值: true 4 2
-- 挂起函数型协程
-- 在函数中使用 coroutine.yield(返回值1, 返回值2, ...返回值n)
myFunction4 = function()
local i = 1
while true do
for j = 1, 3 do
print("myFunction4中打印值" .. " i:" .. i .. " j:" .. j)
coroutine.yield(i, j)
end
i = i + 1
end
end
-- 使用 coroutine.wrap(函数变量) 创建 function 类型协程
-- 使用 协程变量() 分步执行函数,并得到当前返回值
-- wrap 没有第一个“是否执行成功”的返回值
-- 它会直接返回 coroutine.yield() 里传出来的值
myCoroutine4 = coroutine.wrap(myFunction4)
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
print("函数型协程的返回值:", myCoroutine4())
-- myFunction4中打印值 i:1 j:1
-- 函数型协程的返回值: 1 1
-- myFunction4中打印值 i:1 j:2
-- 函数型协程的返回值: 1 2
-- myFunction4中打印值 i:1 j:3
-- 函数型协程的返回值: 1 3
-- myFunction4中打印值 i:2 j:1
-- 函数型协程的返回值: 2 1
-- myFunction4中打印值 i:2 j:2
-- 函数型协程的返回值: 2 2
-- myFunction4中打印值 i:2 j:3
-- 函数型协程的返回值: 2 3
-- myFunction4中打印值 i:3 j:1
-- 函数型协程的返回值: 3 1
-- myFunction4中打印值 i:3 j:2
-- 函数型协程的返回值: 3 2
-- myFunction4中打印值 i:3 j:3
-- 函数型协程的返回值: 3 3
-- myFunction4中打印值 i:4 j:1
-- 函数型协程的返回值: 4 1
-- myFunction4中打印值 i:4 j:2
-- 函数型协程的返回值: 4 2
print("**********知识点四 协程的状态************")
-- coroutine.status(协程变量) 可以得到当前协程的状态
-- 协程变量必须是 coroutine.create 创建出来的 thread 类型
-- coroutine.wrap 返回的是 function,不能直接传给 coroutine.status
-- 协程常见状态有:
-- suspended:暂停,刚创建但还没执行,或者执行到 yield 后停住
-- running:正在运行
-- dead:已经执行结束
-- normal:协程恢复了另一个协程时可能出现,基础阶段先知道有这个状态即可
print(coroutine.status(myCoroutine1)) -- dead,因为 myCoroutine1 已经执行完毕
-- print(coroutine.status(myCoroutine2)) -- 报错,因为 myCoroutine2 是 wrap 返回的函数型协程
print(coroutine.status(myCoroutine3)) -- suspended,因为 myCoroutine3 执行到 yield 后暂停
-- print(coroutine.status(myCoroutine4)) -- 报错,因为 myCoroutine4 是 wrap 返回的函数型协程
myFunction5 = function()
print("我是myFunction5")
-- 当前协程正在运行中,所以这里打印 running
print(coroutine.status(myCoroutine5))
coroutine.yield()
end
myCoroutine5 = coroutine.create(myFunction5)
coroutine.resume(myCoroutine5) -- 在函数中打印 running
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com