企業(yè)網(wǎng)站建設(shè)的成本構(gòu)成便宜的seo網(wǎng)絡(luò)營銷推廣
文章目錄
- 協(xié)程
- 協(xié)程的定義和調(diào)度
- Status
- Running
協(xié)程
協(xié)程是一種并發(fā)操作,相比于線程,線程在執(zhí)行時(shí)往往是并行的,并且線程在創(chuàng)建銷毀執(zhí)行時(shí)極其消耗資源,并且過長的執(zhí)行時(shí)間會造成主進(jìn)程阻塞。而協(xié)程可以以并發(fā)時(shí)輪值時(shí)間片來執(zhí)行,優(yōu)點(diǎn)是不會阻塞,消耗資源少,可以手動控制。至于協(xié)程和線程的區(qū)別,什么是并發(fā)并行,請自行查閱或者學(xué)習(xí)操作系統(tǒng)理論知識。
協(xié)程的定義和調(diào)度
在Unity中,由于游戲是單線程的(這是為了其他線程不阻塞進(jìn)程),因此我們常常需要使用協(xié)程。在Lua中也支持協(xié)程,例如下列代碼:
Corou1 =coroutine.create(function ()print("我是協(xié)程1")
end)
print(Corou1)
Corou2 = coroutine.wrap(function ()print("我是協(xié)程2")
end)
print(Corou2)
coroutine.resume(Corou1) --開始或繼續(xù)協(xié)程
Corou2() --運(yùn)行函數(shù)
輸出:
thread: 00CAEC00
function: 00CA0578
我是協(xié)程1
我是協(xié)程2
我們可以用兩種不同的方法創(chuàng)建協(xié)程,不過返回值一個(gè)是協(xié)程(雖然thread是線程),一個(gè)是函數(shù)。所以對這兩個(gè)協(xié)程的運(yùn)行方式也不同。如何理解這兩種方式?我想用C#的例子:
void StartCorou() --function類型
{StartCoroutine(Coroutine()); --thread類型直接執(zhí)行
}IEnumerator Coroutine()
{
}
thread類型定義的就是協(xié)程本身,因此我們可以用lua提供的協(xié)程table中的方法來調(diào)用,而function類型更像是定義了一個(gè)啟動函數(shù),通過調(diào)用這個(gè)函數(shù)來執(zhí)行。
在Lua中的協(xié)程有一個(gè)優(yōu)點(diǎn):我們可以手動執(zhí)行
Corou1 =coroutine.create(function ()local i = 1while true doprint(i)i = i + 1coroutine.yield(i) --yield也可以返回end
end)coroutine.resume(Corou1)
a,b = coroutine.resume(Corou1)
print(a,b)
coroutine.resume(Corou1)輸出:
1
2
true 3
3 通過注釋我們可以發(fā)現(xiàn),resume第一個(gè)返回固定為成功判斷,然后返回yield提供的變長參數(shù)
function coroutine.resume(co: thread, val1?: any, ...any)-> success: boolean2. ...any
可以看到,對于進(jìn)入了yield的協(xié)程,需要我們手動執(zhí)行resume才能繼續(xù)執(zhí)行。而非自動地輪換時(shí)間片。這樣有利有弊,但我認(rèn)為在調(diào)度上更加靈活了。
使用wrap的話:
function f1()local i = 1while true doprint(i)i = i + 1coroutine.yield(i) end
end
b = coroutine.wrap(f1)
print("返回值"..b())
print("返回值"..b())
print("返回值"..b())輸出:
1
返回值2
2
返回值3
3
返回值4function coroutine.wrap(f: fun(...any):...unknown)-> fun(...any):...unknown
使用wrap則我們發(fā)現(xiàn),wrap并不返回成功判斷,而是直接返回yield給出的變長參數(shù),這是由于其內(nèi)定義的函數(shù)就只接收變長參數(shù)。
Status
Lua中的協(xié)程總共有四種狀態(tài):
function coroutine.status(co: thread)-> "dead"|"normal"|"running"|"suspended"
以字符串形式返回協(xié)程 co 的狀態(tài)。return #1:| "running" 正在運(yùn)行。| "suspended" 掛起或是還沒有開始運(yùn)行。| "normal" 是活動的,但并不在運(yùn)行。| "dead" 運(yùn)行完主體函數(shù)或因錯(cuò)誤停止。
讓我們從下面的例子看看協(xié)程什么時(shí)候會進(jìn)入這些狀態(tài):
C2 = coroutine.create(function ()print("協(xié)程2執(zhí)行")print("此時(shí)協(xié)程1:"..coroutine.status(Corou1))coroutine.yield()
end)
Corou1 =coroutine.create(function ()local i = 1while i<3 doprint(i)i = i + 1if i==2 thencoroutine.resume(C2)endprint(coroutine.status(Corou1))coroutine.yield() end
end)
print(coroutine.status(Corou1))
print("######")
coroutine.resume(Corou1)
print(coroutine.status(Corou1))
print("######")
coroutine.resume(Corou1)
print(coroutine.status(Corou1))
print("######")
coroutine.resume(Corou1)
print(coroutine.status(Corou1))
print("######")輸出:
suspended
######
1
協(xié)程2執(zhí)行
此時(shí)協(xié)程1:normal
running
suspended
######
2
running
suspended
######
dead
######
從上述例子中看到,當(dāng)協(xié)程未啟動以及暫停中等待下一次resume時(shí),其狀態(tài)是suspended。而當(dāng)協(xié)程正在執(zhí)行時(shí)狀態(tài)是running,當(dāng)協(xié)程1執(zhí)行切換到協(xié)程2時(shí),協(xié)程1的狀態(tài)是normal。最后當(dāng)協(xié)程1退出時(shí)其狀態(tài)是dead。
Running
running函數(shù)可以得到當(dāng)前正在運(yùn)行的協(xié)程(的地址)。
function coroutine.running()-> running: thread2. ismain: boolean
返回當(dāng)前正在運(yùn)行的協(xié)程加一個(gè)布爾量。 如果當(dāng)前運(yùn)行的協(xié)程是主線程,其為真。
(我試了一下沒接收到這個(gè)bool,不知道什么情況)
用例:
Corou1 =coroutine.create(function ()local i = 1while i<3 doprint(i)i = i + 1print("協(xié)程1狀態(tài):"..coroutine.status(Corou1))print(coroutine.running())coroutine.yield() end
end)
coroutine.resume(Corou1)輸出:
1
協(xié)程1狀態(tài):running
thread: 00A7E1F8 <-- 協(xié)程1的地址
先拋出一個(gè)問題:如果在上述的同樣代碼中,執(zhí)行協(xié)程2時(shí)print這個(gè)running函數(shù),請問可以得到什么?考慮到協(xié)程1在協(xié)程2運(yùn)行時(shí)是normal狀態(tài),當(dāng)前運(yùn)行(running)的協(xié)程應(yīng)當(dāng)是協(xié)程2
C2 = coroutine.create(function ()print("協(xié)程2執(zhí)行")print(coroutine.running())print("此時(shí)協(xié)程1:" .. coroutine.status(Corou1))print("協(xié)程2執(zhí)行結(jié)束")coroutine.yield()
end)
Corou1 =coroutine.create(function ()local i = 1while i<3 doprint(i)i = i + 1if i==2 thencoroutine.resume(C2)endprint("協(xié)程1狀態(tài):"..coroutine.status(Corou1))print(coroutine.running())coroutine.yield() end
end)
coroutine.resume(Corou1)
coroutine.resume(Corou1)輸出:
1
協(xié)程2執(zhí)行
thread: 00C4CFE8
此時(shí)協(xié)程1:normal
協(xié)程2執(zhí)行結(jié)束
協(xié)程1狀態(tài):running
thread: 00C4D408
2
協(xié)程1狀態(tài):running
thread: 00C4D408