執行緒模型
- 最近在寫有關 go 的執行緒,但是突然一下子就卡住了,之前明明看過很多文章,也寫過協程池,為什麼一到實戰就不行了呢,好吧,其實是寫的不多,但是快速上手也很重要,為什麼不偷懶下直接套模板呢,以下是我總結的一些可以直接套用的簡易模板
前置知識
快速開始
- 一個十分簡單的例子
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("hello")
}()
wg.Wait()
}
嘗試開三個協程,一個生產者,一個消費者,生產者負責組裝傳送資訊,消費者負責接收計算
inCh := make(chan int, len(nums))
go func() {
defer close(inCh)
for _, num := range nums {
inCh <- num
}
}()
return inCh
}
outCh := make(chan int, len(inCh))
go func() {
defer close(outCh)
for in := range inCh {
outCh <- in*in
}
}()
return outCh
}
func main() {
in := producer(1, 2, 3, 4)
out := consumer(in)
for i:= range out {
fmt.Println(i)
}
}
考慮多種情況
1. M個接收者和一個傳送者,傳送者通過關閉用來傳輸資料的通道來傳遞傳送結束訊號
type mc struct {
cond *sync.Cond
done bool
}
func New() *mc {
return &mc{
cond: sync.NewCond(&sync.Mutex{}),
done: false,
}
}
func (m *mc) producer(nums ...int) <-chan int {
inCh := make(chan int, len(nums))
go func() {
m.cond.L.Lock()
defer func() {
close(inCh)
m.cond.L.Unlock()
m.cond.Broadcast()
m.done = true
}()
for _, num := range nums {
inCh <- num
}
}()
return inCh
}
func (m *mc) consumer(inCh <-chan int) <-chan int {
outCh := make(chan int, len(inCh))
go func() {
m.cond.L.Lock()
defer func() {
defer m.cond.L.Unlock()
close(outCh)
}()
for !m.done {
m.cond.Wait()
}
for ch := range outCh {
outCh <- ch
}
}()
return inCh
}
func merge(chs ...<-chan int, ) <-chan int {
var wg sync.WaitGroup
outCh := make(chan int, len(chs))
collect := func(in <-chan int) {
defer wg.Done()
for n := range in {
outCh <- n
}
}
wg.Add(len(chs))
for _, ch := range chs {
go collect(ch)
}
go func() {
wg.Wait()
close(outCh)
}()
return outCh
}
func main() {
m := New()
inCh := m.producer(1, 2, 3, 4, 5, 6)
out1 := m.consumer(inCh)
out2 := m.consumer(inCh)
out3 := m.consumer(inCh)
for i := range merge(out1, out2, out3) {
fmt.Println(i)
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結