初识lua协同程序

协程类似与线程,但与线程不同,线程可以多个线程同时运行,但是协程需要彼此协作的运行,一个具有多个协程的程序任意时刻只能运行一个协程,并且在运行协程只会在其显示地要求挂起时,才会暂停。

一个协程有4种不同的状态:挂起,运行,死亡和正常。创建一个协程时,他处于挂起状态。

coroutine.status(co)检查协程的状态

coroutine.resume(co)用于启动或再次启动一个协程的执行,将其由挂起改为运行。

coroutine.yield()用于将一个运行中的协同程序挂起,而且之后可以用resume再运行

当一个协程A唤醒另一个协程B时,协程A即不是挂起状态,也不是运行状态,此时处于正常状态。

lua的协程可以通过一对resume yield来交换数据。

co = coroutine.create(function(alb,c)

        print("co",alb,c) 

        end )

coroutine.resume(co,1,2,3)--->co 1 2 3

co = coroutine.create(function(a,b)

        coroutine.yield(a+b,a-b) 

        end )

print(coroutine.resume(co,20,10)) ---->true 30 10

lua提供的是非对称的协同程序,用两个函数来控制协同程序的执行。

1 协程可以用来实现迭代器

常规实现:

function P(a,n)

n = n or #a

if n <= 1 then

    printResult(a)

else

    for i  =1 , n do

    a[n],a[i] = a[i],a[n]

    P(a,n-1)

    a[n],a[i]=a[i],a[n]

    end

end

end

协程实现

function permutations(a)

    return coroutine.wrap(function() P(a) end)

end

function P(a,n)

n = n or #a

if n<= 1 then

    coroutine.yield(a)

else

    for i  =1 , n do

        a[n],a[i] = a[i],a[n]

        P(a,n-1)

        a[n],a[i]=a[i],a[n]

    end

end

end

coroutine.wrap创建一个新的协程,不同于create,wrap并不返回协程本身,而是返回一个函数。

2 协程实现下载

协程是非抢占式的,因此当有一个线程被阻塞了,其他的线程都会被阻塞,这是不可以接受的。

下载的时候,如果同时下载多个文件,为每个下载任务创建一个新的线程,只要一个线程无可用数据,就可以将控制权转让给一个简单的调度程序,这个调度程序会去调度其他的下载程序。

function download(host ,file)

    local c = assert(socket.connect(host,80))

    local count = 0

    c:send("GET"..file.."HTTP/1.0/r/n")

    while true do

        local s , status , partial = receive(c)

        count = count + #(s or partial)

        if status == "closed" then break end

    end

    c:close()

    print(file , count)

    end

function receive (connection)

    connection:settimeout(0)

    local s , status , partial = connection:receive(2^10)

    if status == "timeout" then

         coroutine.yield(connection)   

     end

    return s or partial , status

end

threads = {}

function get (host , file)

    local co = coroutine.create( function ()

        download(host , file)

     end)

    table.insert(threads, co)

end

function dispatch()

    local i = 1

    local connections = {}

    while true do

        if threads[i] == nil then

            if threads[1] == nil then break end

            i = 1

            connections = {}

         end

        local status , res = coroutine.resume(threads[i])

        if not res then

            table.remove(threads,i)

        else

            i = i + 1

            if #connection == #threads then

                socket.select(connections) --->将所有超时的连接收集到一个connections的table中,receive会将超时的连接通过yield传递,如果所有的连接都超时,调度程序就调用select来等待这些连接的状态发生变化。

            end

         end

    end

end









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值