• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

lua中的协程

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

lua中的协程和线程类似:

  1. 协程拥有自己的独立的栈,局部变量,和指令;

  2. 所有协程都可以共享全局变量;

  3. 协程不能像线程那样并行执行,协程之间需要相互协调执行,同一个时刻只能运行一个协程;

 

如何使用协程:

  coroutine.create:创建一个协程,返回一个协程句柄;

  coroutine.status:查看一个协程的状态,suspended,running,dead,normal;

  coroutine.resume:恢复一个协程的执行,如果正常就返回true,错误返回false和一条错误信息;

  coroutine.yield:挂起一个协程的执行;

  resume-yield的数据返回:

  例子:

  local co2 = coroutine.create(function(a, b, c)
    return coroutine.yield(a + b, b + c, c + a)
  end)

  print("resume", coroutine.resume(co2, 1, 2, 3)) // 打印 resume true 3 5 4 yield时,返回yield的参数
  print("resume", coroutine.resume(co2, 1, 2, 3)) // 打印 resume true 1 2 3 resume时,返回resume的参数

 

生产者和消费者实例:

以消费者为驱动,即主循环在消费者,这里有两个消费者,同时向一个生产者获取数据。生产者每产生一个数据就会被挂起,知道下次被消费者激活。

协程程序一旦执行完成,协程状态就会被设置为dead,即死亡状态,如果试图用resume去激活一个死亡状态的协程会出现错误,可以通过判断resume的第一个返回判断协程运行是否正常。

local producer = coroutine.create(function()
    local i = 0;

    while true do
        i = i + 1;
        --print(i)

        coroutine.yield(i)
    end
end)

function comsumer_func()
    local status = 0 data = 0
    while true do
        if (data >= 10) then
            break
        end

        status, data = coroutine.resume(producer)
        print("comsumer1:", data)

        coroutine.yield()
    end
end

local comsumer1 = coroutine.create(comsumer_func)
local comsumer2 = coroutine.create(comsumer_func)
local comsumers = coroutine.create(function(...)
    local threads = {...}
    local threads_status = {}
    for i, v in ipairs(threads) do
        threads_status[i] = true
    end

    while true do
        local status = false

        for i, v in ipairs(threads) do
            if (threads_status[i]) then
                threads_status[i] = coroutine.resume(threads[i])
            end

            status = status or threads_status[i];
        end

        if (not status) then
            break
        end
    end
end)

print(coroutine.resume(comsumers, comsumer1, comsumer2))

print(coroutine.status(producer))
print(coroutine.status(comsumer1))
print(coroutine.status(comsumer2))

 

排列组合迭代器实例:

function generate(t, i, n)
    if (i >= n) then
        coroutine.yield(t)
    else
        for j = i, n do
            t[j], t[i] = t[i], t[j];
            generate(t, i+1, n);
            t[j], t[i] = t[i], t[j];
        end
    end
end

function iter(t)
    local co = coroutine.create(function()
        generate(t, 1, #t)
    end)

    return function()
        local status, data = coroutine.resume(co)
        return data
    end
end

local t = {"a", "b", "c", "e"}
for t in iter(t) do
    for j = 1, #t do
            io.write(t[j])
        end
        io.write("\n")
end

 

多线程下载文件实例:

require "socket"

function http_get_file(host, file)
    local con = assert(socket.connect(host, 80))
    con:settimeout(0)
    con:send("GET "..file.." HTTP/1.0\r\n\r\n")

    print("start to download "..file)

    while true do
        local data, status, partial = con:receive(128)
        io.write(data or partial)

        if status == "timeout" then
            --print("timeout")
            coroutine.yield(con)
        elseif status == "closed" then
            print("closed")
            break 
        end
    end

    con:close()
end

local download_threads = {}

function create_download_task(host, file)
    local thread = assert(coroutine.create(function()
        http_get_file(host, file)
    end))

    print("thread", thread)

    table.insert(download_threads, thread)
end

function start_to_download()
    local i = 1
    while true do
        if (#download_threads == 0) then break end

        if (download_threads[i]) then
            local status, con = coroutine.resume(download_threads[i])

            if not con then
                table.remove(download_threads, i)
                i = i - 1
            end
        end

        i = (i + 1)
        if i > #download_threads then
            i = 1
        end
    end
end

create_download_task("news.zol.com.cn", "/591/5916908.html")
create_download_task("www.baidu.com", "/")

start_to_download()

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Unity_Lua_VS环境下入门操作发布时间:2022-07-22
下一篇:
基于模板特化的Lua自动绑定系统发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap