本文主要是介绍初识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
这篇关于初识lua协同程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!