一、併發程式設計模式
在上兩篇文章中我們主要介紹了併發goroutine和channel,現在我們來介紹一下golang的併發模式,不像golang的設計模式,這裡來介紹一下常用的併發模式:
- 生成器
程式分析:msgGen()將c := make(chan string)返回給m1,在for中等待併發啟動傳送資料給m1,m1立即將資料送出並列印。package main import ( "fmt" "math/rand" "time" ) //生成器msgGen func msgGen() chan string { c := make(chan string) //啟動併發,真正生成資料 go func(){ i := 0 for { //生成時間在範圍:0~2000毫秒 time.Sleep(time.Duration(rand.Intn(2000)) * time.Millisecond) c <- fmt.Sprintf("message :%d", i) i++ } }() return c } func main() { m1 := msgGen() for{ fmt.Println(<-m1) } }
- 服務/任務
看下面程式碼:在生成器的基礎之上可以提供多個服務/任務,如上面程式碼中的m1,m2是使用同一個生成器的兩個服務/任務,而m1和m2是兩個獨立的服務/任務,我們如果拿到m1j就可以和m1j互動,拿到m2就可以和m2進行互動。func main() { m1 := msgGen() //開啟任務m1 M2 := msgGen() //開啟任務m2 for{ fmt.Println(<-m1) fmt.Println(<-m2) } }
列印結果:package main import ( "fmt" "math/rand" "time") func msgGen(name string) chan string { c := make(chan string) go func(){ i := 0 for { time.Sleep(time.Duration(rand.Intn(2000)) * time.Millisecond) c <- fmt.Sprintf("service: %s, message :%d", name, i) i++ } }() return c } func main() { m1 := msgGen("service1") M2 := msgGen("sercive2") for{ fmt.Println(<-m1) fmt.Println(<-m2) } }
service: service1, message :0
service: sercive2, message :0
service: service1, message :1
service: sercive2, message :1
service: service1, message :2
service: sercive2, message :2
service: service1, message :3
service: sercive2, message :3
service: service1, message :4
service: sercive2, message :4
service: service1, message :5
service: sercive2, message :5
service: service1, message :6
service: sercive2, message :6
……
……
……- 同時等待多工:兩種方法
從上面的列印結果可以看出兩個任務是一起進行的,現在我們需要將兩個結果交替列印:
方法一:將兩個channel的資料放進一個節點中,然後在傳送到第三個channel中
下面來看是如何實現的:func fanIn(c1, c2 chan string) chan string{ c := make(chan string) go func() { for{ c <- <-c1 } }() go func() { for{ c <- <-c2 } }() return c }
這是完整程式碼:
package main
import (
"fmt"
"math/rand" "time")
func msgGen(name string) chan string {
c := make(chan string)
go func(){
i := 0
for {
time.Sleep(time.Duration(rand.Intn(2000)) * time.Millisecond)
c <- fmt.Sprintf("service: %s, message :%d", name, i)
i++
}
}()
return c
}
func fanIn(c1, c2 chan string) chan string{
c := make(chan string)
go func() {
for{
c <- <-c1
}
}()
go func() {
for{
c <- <-c2
}
}()
return c
}
func main() {
m1 := msgGen("service1")
m2 := msgGen("sercive2")
m := fanIn(m1, m2)
for{
fmt.Println(<-m)
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結