lua中的协程

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()

转载于:https://www.cnblogs.com/iRidescent-ZONE/p/5640917.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值