lua協程----ngx-lua線程學習筆記


   

--[[
- @desc   lua數據輸出
- @param  string   字符串 
- return  string
--]]
function dump(v)
    if not __dump then
        function __dump(v, t, p)    
            local k = p or "";

            if type(v) ~= "table" then
                table.insert(t, k .. " : " .. tostring(v));
            else
                for key, value in pairs(v) do
                    __dump(value, t, k .. "[" .. key .. "]");
                end
            end
        end
    end

    local t = {'======== Lib:Dump Content ========'};
    __dump(v, t);
    print(table.concat(t, "\n"));
end

--coroutine  是一個table 有一些方法 create  wrap 

--create() 創建coroutine,返回coroutine, 參數是一個函數,當和resume配合使用的時候就喚醒函數調用


--resume()   (1)第一次調用的作用是 激活coroutine,也就是讓協程函數開始運行;
             (2)第大於1次調用的作用是 喚醒yield,使掛起的協同接着上次的地方繼續運行。該函數可以傳入參數
                --1. 一定要注意區分,第一次啟動coroutine的時候,resume的參數傳給匿名函數(以后不在進行匿名函數的形參賦值);
                --2. 在喚醒yield的時候,參數是傳遞給yield()的。直接從yield()的位置往下執行
                --3. 匿名函數執行完畢后,再次調用coroutine.resume不在起作用,因為協成狀態已經停止
                
                
--coroutine.yield() 掛起coroutine, 相當於是一個特殊的return語句,只是它只是暫時性的返回(掛起),並且yield可以像return一樣帶有返回參數,這些參數是傳遞給resume的。
--coroutine.status() 查看coroutine的狀態
--注:coroutine的狀態有三種:dead,suspend,running,具體什么時候有這樣的狀態請參考下面的程序

--coroutine.wrap() 創建coroutine,返回一個函數,一旦你調用這個函數,就進入coroutine,和create功能重復
--coroutine.running() 返回正在跑的coroutine,一個coroutine就是一個線程,當使用running的時候,就是返回一個corouting的線程號








coroutineFunc = function (a, b) 
    for i = 1, 10 do
        ngx.say(i, a, b)
        coroutine.yield()
    end
end

co2 = coroutine.create(coroutineFunc)        --創建協同程序co2
coroutine.resume(co2, 100, 200)                -- 1 100 200 開啟協同,傳入參數用於初始化
coroutine.resume(co2)                        -- 2 100 200 
coroutine.resume(co2, 500, 600)                -- 3 100 200 繼續協同,傳入參數無效

co3 = coroutine.create(coroutineFunc)        --創建協同程序co3
coroutine.resume(co3, 300, 400)                -- 1 300 400 開啟協同,傳入參數用於初始化
coroutine.resume(co3)                        -- 2 300 400 
coroutine.resume(co3)                        -- 3 300 400 



co = coroutine.create(function (a, b)
                   dump(a);
                   ngx.say("co", a, b);
                   ngx.say("cooo", coroutine.yield());--第一次進來的時候這里直接停止, cooo沒有輸出 第二次進來在停止的地方繼續執行
                   
                   ngx.say("cooooo", coroutine.yield());--第三次進來時 在停止的地方繼續執行  cooooo輸出
               end)
               
coroutine.resume(co, 1, 2)        --co12
ngx.say("\r\n");
coroutine.resume(co, 3, 4, 5)        --co 1 2 3 4 5,這里的兩個數字參數由resume傳遞給yield 
coroutine.resume(co, 7,8) 
coroutine.resume(co, 6,9) --第四次不執行










produceFunc = function()
    while true do
        local value = io.read()
        print("produce: ", value)
        coroutine.yield(value)        --返回生產的值
    end
end

filteFunc = function(p)
    while true do
        local status, value = coroutine.resume(p);  --執行 produceFunc函數
        value = value *100            --放大一百倍
        coroutine.yield(value)
    end
end

consumer = function(f, p)
    while true do
        local status, value = coroutine.resume(f, p);  --喚醒生產者進行生產  執行filteFunc函數並把produceFunc當做參數傳入 
        print("consume: ", value)
    end
end

--消費者驅動的設計,也就是消費者需要產品時找生產者請求,生產者完成生產后提供給消費者
producer = coroutine.create(produceFunc)
filter = coroutine.create(filteFunc)
consumer(filter, producer)





 

------ngx_lua多線程 案例------
local t1 = ngx.now()  
local function capture(uri, args)  

   return ngx.location.capture(uri, args)  --請求本地的url地址
 
  --[[ 
   local res1,res2 = ngx.location.capture_multi({ -- 一次請求多個本地url
              {"/api1", {args = ngx.req.get_uri_args()}},  
              {"/api2", {args = ngx.req.get_uri_args()}}  
  
        })  
  --]]
end  

local thread1 = ngx.thread.spawn(capture, "/test", {args = ngx.req.get_uri_args()})  --開啟第一個線程; 第一個參數是匿名函數 后面的參數是匿名函數的參數
local thread2 = ngx.thread.spawn(capture, "/test", {args = ngx.req.get_uri_args()})  --開啟第二個線程
local ok1, res1 = ngx.thread.wait(thread1)  --等待第一個線程的返回結果  
local ok2, res2 = ngx.thread.wait(thread2)  --等待第二個線程的返回結果
local t2 = ngx.now()  

dump(ok1); 
dump(res1);
dump(t1 .. '--' .. t2);
 
ngx.print("<br/>", res1.body, tostring(t2-t1))  
ngx.print("<br/>", res2.body, tostring(t2-t1))  



 
 
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM