zoukankan      html  css  js  c++  java
  • 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("
    ")
    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
    
    ")
    
        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()
  • 相关阅读:
    妙趣横生的HTML5 Page Visibility API
    Django ElasticSearch Ionic 打造 GIS 移动应用 —— 架构设计
    HT for Web的HTML5树组件延迟加载技术实现
    mobileSite开发Tips
    [译] 沙箱中的间谍
    使用Javascript获取剪贴板图片的DataURL
    竖屏旋转摄像头预览数据90度
    centos下安装 gcc,g++,gdb
    centos7连接网络不可达的解决方法
    OpenGL里的坐标系统以及其变换
  • 原文地址:https://www.cnblogs.com/iRidescent-ZONE/p/5640917.html
Copyright © 2011-2022 走看看