在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
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) print("resume", coroutine.resume(co2, 1, 2, 3)) // 打印 resume true 3 5 4 yield时,返回yield的参数
生产者和消费者实例: 以消费者为驱动,即主循环在消费者,这里有两个消费者,同时向一个生产者获取数据。生产者每产生一个数据就会被挂起,知道下次被消费者激活。 协程程序一旦执行完成,协程状态就会被设置为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() |
请发表评论