13.协同程序

13.协同程序


13.1 知识点

协程的创建

  • 创建协程有两种方法:coroutine.createcoroutine.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 的位置继续往下跑。
  • 可以先把它理解成:函数执行到一半先停住,下一次再从停住的位置继续执行。
  • 基础阶段先掌握 yieldresume / 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

×

喜欢就点赞,疼爱就打赏