日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
在 Go 語言中管理 Concurrency 的三種方式

相信大家踏入 Go 語言的世界,肯定是被強(qiáng)大的并發(fā)(Concurrency)所吸引,Go 語言用最簡(jiǎn)單的關(guān)鍵字go就可以將任務(wù)丟到后臺(tái)處理,但是開發(fā)者怎么有效率的控制并發(fā),這是入門 Go 語言必學(xué)的技能,本章會(huì)介紹幾種方式來帶大家認(rèn)識(shí)并發(fā),而這三種方式分別對(duì)應(yīng)到三個(gè)不同的名詞:WaitGroup,Channel,及 Context。下面用簡(jiǎn)單的范例帶大家了解。

10年的達(dá)坂城網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都全網(wǎng)營(yíng)銷的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整達(dá)坂城建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。成都創(chuàng)新互聯(lián)從事“達(dá)坂城網(wǎng)站設(shè)計(jì)”,“達(dá)坂城網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

WaitGroup

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

 
 
 
  1. package main 
  2.  
  3. import ( 
  4.     "fmt" 
  5.     "sync" 
  6.  
  7. func main() { 
  8.     var wg sync.WaitGroup 
  9.     i := 0 
  10.     wg.Add(3) //task count wait to do 
  11.     go func() { 
  12.         defer wg.Done() // finish task1 
  13.         fmt.Println("goroutine 1 done") 
  14.         i++ 
  15.     }() 
  16.     go func() { 
  17.         defer wg.Done() // finish task2 
  18.         fmt.Println("goroutine 2 done") 
  19.         i++ 
  20.     }() 
  21.     go func() { 
  22.         defer wg.Done() // finish task3 
  23.         fmt.Println("goroutine 3 done") 
  24.         i++ 
  25.     }() 
  26.     wg.Wait() // wait for tasks to be done 
  27.     fmt.Println("all goroutine done") 
  28.     fmt.Println(i) 

Channel

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

 
 
 
  1. package main 
  2.  
  3. import ( 
  4.     "fmt" 
  5.     "time" 
  6.  
  7. func main() { 
  8.     exit := make(chan bool) 
  9.     go func() { 
  10.         for { 
  11.             select { 
  12.             case <-exit: 
  13.                 fmt.Println("Exit") 
  14.                 return 
  15.             case <-time.After(2 * time.Second): 
  16.                 fmt.Println("Monitoring") 
  17.             } 
  18.         } 
  19.     }() 
  20.     time.Sleep(5 * time.Second) 
  21.     fmt.Println("Notify Exit") 
  22.     exit <- true //keep main goroutine alive 
  23.     time.Sleep(5 * time.Second) 

上面的例子可以發(fā)現(xiàn),用了一個(gè) Gogourtine 和 Channel 來控制??梢韵胂癞?dāng)后臺(tái)有無數(shù)個(gè) Goroutine 的時(shí)候,我們就需要用多個(gè) Channel 才能進(jìn)行控制,也許 Goroutine 內(nèi)又會(huì)產(chǎn)生 Goroutine,開發(fā)者這時(shí)候就會(huì)發(fā)現(xiàn)已經(jīng)無法單純使用 Channel 來控制多個(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í)候通過 context 方式是最快的了。

 
 
 
  1. package main 
  2.  
  3. import ( 
  4.     "context" 
  5.     "fmt" 
  6.     "time" 
  7.  
  8. func foo(ctx context.Context, name string) { 
  9.     go bar(ctx, name) // A calls B 
  10.     for { 
  11.         select { 
  12.         case <-ctx.Done(): 
  13.             fmt.Println(name, "A Exit") 
  14.             return 
  15.         case <-time.After(1 * time.Second): 
  16.             fmt.Println(name, "A do something") 
  17.         } 
  18.     } 
  19.  
  20. func bar(ctx context.Context, name string) { 
  21.     for { 
  22.         select { 
  23.         case <-ctx.Done(): 
  24.             fmt.Println(name, "B Exit") 
  25.             return 
  26.         case <-time.After(2 * time.Second): 
  27.             fmt.Println(name, "B do something") 
  28.         } 
  29.     } 
  30.  
  31. func main() { 
  32.     ctx, cancel := context.WithCancel(context.Background()) 
  33.     go foo(ctx, "FooBar") 
  34.     fmt.Println("client release connection, need to notify A, B exit") 
  35.     time.Sleep(5 * time.Second) 
  36.     cancel() //mock client exit, and pass the signal, ctx.Done() gets the signal  time.Sleep(3 * time.Second) 
  37.     time.Sleep(3 * time.Second) 
  38.  
  39. package main 
  40.  
  41. import ( 
  42.     "context" 
  43.     "fmt" 
  44.     "time" 
  45.  
  46. func foo(ctx context.Context, name string) { 
  47.     go bar(ctx, name) // A calls B 
  48.     for { 
  49.         select { 
  50.         case <-ctx.Done(): 
  51.             fmt.Println(name, "A Exit") 
  52.             return 
  53.         case <-time.After(1 * time.Second): 
  54.             fmt.Println(name, "A do something") 
  55.         } 
  56.     } 
  57.  
  58. func bar(ctx context.Context, name string) { 
  59.     for { 
  60.         select { 
  61.         case <-ctx.Done(): 
  62.             fmt.Println(name, "B Exit") 
  63.             return 
  64.         case <-time.After(2 * time.Second): 
  65.             fmt.Println(name, "B do something") 
  66.         } 
  67.     } 
  68.  
  69. func main() { 
  70.     ctx, cancel := context.WithCancel(context.Background()) 
  71.     go foo(ctx, "FooBar") 
  72.     fmt.Println("client release connection, need to notify A, B exit") 
  73.     time.Sleep(5 * time.Second) 
  74.     cancel() //mock client exit, and pass the signal, ctx.Done() gets the signal  time.Sleep(3 * time.Second) 
  75.     time.Sleep(3 * time.Second) 

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

總結(jié)

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

  • WaitGroup:需要將單一個(gè)工作分解成多個(gè)子任務(wù),等到全部完成后,才能進(jìn)行下一步,這時(shí)候用 WaitGroup 最適合了
  • Channel + Select:Channel 只能用在比較單純的 Goroutine 情況下,如果要管理多個(gè) Goroutine,建議還是 走 context 會(huì)比較適合
  • Context:如果您想一次控制全部的 Goroutine,相信用 context 會(huì)是最適合不過的。

當(dāng)前題目:在 Go 語言中管理 Concurrency 的三種方式
本文URL:http://www.dlmjj.cn/article/dhdoopd.html