真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Go語(yǔ)言中怎么對(duì)Concurrency進(jìn)行管理

這篇文章給大家介紹 Go語(yǔ)言中怎么對(duì)Concurrency進(jìn)行管理 ,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

創(chuàng)新互聯(lián)2013年開(kāi)創(chuàng)至今,是專(zhuān)業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元大寧做網(wǎng)站,已為上家服務(wù),為大寧各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話(huà):13518219792

WaitGroup

先來(lái)了解有什么情境需要使用到  WaitGroup,假設(shè)您有兩臺(tái)機(jī)器需要同時(shí)上傳最新的代碼,兩臺(tái)機(jī)器分別上傳完成后,才能執(zhí)行最后的重啟步驟。就像是把一個(gè)工作同時(shí)拆成好幾份同時(shí)一起做,可以減少時(shí)間,但是最后需要等到全部做完,才能執(zhí)行下一步,這時(shí)候就需要用到  WaitGroup 才能做到。

package main  import (     "fmt"     "sync" )  func main() {     var wg sync.WaitGroup     i := 0     wg.Add(3) //task count wait to do     go func() {         defer wg.Done() // finish task1         fmt.Println("goroutine 1 done")         i++     }()     go func() {         defer wg.Done() // finish task2         fmt.Println("goroutine 2 done")         i++     }()     go func() {         defer wg.Done() // finish task3         fmt.Println("goroutine 3 done")         i++     }()     wg.Wait() // wait for tasks to be done     fmt.Println("all goroutine done")     fmt.Println(i) }

Channel

另外一種實(shí)際的案例就是,我們需要主動(dòng)通知一個(gè) Goroutine 進(jìn)行停止的動(dòng)作。換句話(huà)說(shuō),當(dāng) App 啟動(dòng)時(shí),會(huì)在后臺(tái)跑一些監(jiān)控程序,而當(dāng)整個(gè) App  需要停止前,需要發(fā)個(gè) Notification 給后臺(tái)的監(jiān)控程序,將其先停止,這時(shí)候就需要用到 Channel 來(lái)通知??聪孪旅孢@個(gè)例子:

package main  import (     "fmt"     "time" )  func main() {     exit := make(chan bool)     go func() {         for {             select {             case <-exit:                 fmt.Println("Exit")                 return             case <-time.After(2 * time.Second):                 fmt.Println("Monitoring")             }         }     }()     time.Sleep(5 * time.Second)     fmt.Println("Notify Exit")     exit <- true //keep main goroutine alive     time.Sleep(5 * time.Second) }

上面的例子可以發(fā)現(xiàn),用了一個(gè) Gogourtine 和 Channel 來(lái)控制??梢韵胂癞?dāng)后臺(tái)有無(wú)數(shù)個(gè) Goroutine 的時(shí)候,我們就需要用多個(gè)  Channel 才能進(jìn)行控制,也許 Goroutine 內(nèi)又會(huì)產(chǎn)生 Goroutine,開(kāi)發(fā)者這時(shí)候就會(huì)發(fā)現(xiàn)已經(jīng)無(wú)法單純使用 Channel 來(lái)控制多個(gè)  Goroutine 了。這時(shí)候解決方式會(huì)是傳遞 Context。

Context

大家可以想像,今天有一個(gè)后臺(tái)任務(wù) A,A 任務(wù)又產(chǎn)生了 B 任務(wù),B 任務(wù)又產(chǎn)生了 C 任務(wù),也就是可以按照此模式一直產(chǎn)生下去,假設(shè)中途我們需要停止 A  任務(wù),而 A 又必須告訴 B 及 C 要一起停止,這時(shí)候通過(guò) context 方式是最快的了。

package main  import (     "context"     "fmt"     "time" )  func foo(ctx context.Context, name string) {     go bar(ctx, name) // A calls B     for {         select {         case <-ctx.Done():             fmt.Println(name, "A Exit")             return         case <-time.After(1 * time.Second):             fmt.Println(name, "A do something")         }     } }  func bar(ctx context.Context, name string) {     for {         select {         case <-ctx.Done():             fmt.Println(name, "B Exit")             return         case <-time.After(2 * time.Second):             fmt.Println(name, "B do something")         }     } }  func main() {     ctx, cancel := context.WithCancel(context.Background())     go foo(ctx, "FooBar")     fmt.Println("client release connection, need to notify A, B exit")     time.Sleep(5 * time.Second)     cancel() //mock client exit, and pass the signal, ctx.Done() gets the signal  time.Sleep(3 * time.Second)     time.Sleep(3 * time.Second) }  package main  import (     "context"     "fmt"     "time" )  func foo(ctx context.Context, name string) {     go bar(ctx, name) // A calls B     for {         select {         case <-ctx.Done():             fmt.Println(name, "A Exit")             return         case <-time.After(1 * time.Second):             fmt.Println(name, "A do something")         }     } }  func bar(ctx context.Context, name string) {     for {         select {         case <-ctx.Done():             fmt.Println(name, "B Exit")             return         case <-time.After(2 * time.Second):             fmt.Println(name, "B do something")         }     } }  func main() {     ctx, cancel := context.WithCancel(context.Background())     go foo(ctx, "FooBar")     fmt.Println("client release connection, need to notify A, B exit")     time.Sleep(5 * time.Second)     cancel() //mock client exit, and pass the signal, ctx.Done() gets the signal  time.Sleep(3 * time.Second)     time.Sleep(3 * time.Second) }

大家可以把 context 想成是一個(gè) controller,可以隨時(shí)控制不確定個(gè)數(shù)的  Goroutine,由上往下,只要宣告context.WithCancel后,再任意時(shí)間點(diǎn)都可以通過(guò)cancel()來(lái)停止整個(gè)后臺(tái)服務(wù)。實(shí)際案例會(huì)用在當(dāng) App  需要重新啟動(dòng)時(shí),要先通知全部 goroutine 停止,正常停止后,才會(huì)重新啟動(dòng) App。

總結(jié)

根據(jù)不同的情境跟狀況來(lái)選擇不同的方式,做一個(gè)總結(jié):

  • WaitGroup:需要將單一個(gè)工作分解成多個(gè)子任務(wù),等到全部完成后,才能進(jìn)行下一步,這時(shí)候用 WaitGroup 最適合了

  • Channel + Select:Channel 只能用在比較單純的 Goroutine 情況下,如果要管理多個(gè) Goroutine,建議還是 走  context 會(huì)比較適合

  • Context:如果您想一次控制全部的 Goroutine,相信用 context 會(huì)是最適合不過(guò)的。

關(guān)于 Go語(yǔ)言中怎么對(duì)Concurrency進(jìn)行管理 就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。


本文標(biāo)題:Go語(yǔ)言中怎么對(duì)Concurrency進(jìn)行管理
網(wǎng)站路徑:http://weahome.cn/article/ppcgoe.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部