Go語言無緩沖通道創(chuàng)建協(xié)程池

Go語言無緩沖通道創(chuàng)建協(xié)程池

這些協(xié)程池通常用于并發(fā)執(zhí)行一組任務,最終組合起來完成某個功能。在這種情況下嚣镜,使用無緩沖通道要比使用緩沖通道好,因為既不需要任務隊列橘蜜,也不需要一組協(xié)程配合執(zhí)行菊匿,并且方便知道什么時候協(xié)程池正在執(zhí)行任務,如果協(xié)程池中的所有協(xié)程都在忙计福,無法處理新的任務跌捆,也能及時通過通道通知調(diào)用者(分配給無緩沖通道的任務未處理會阻塞后續(xù)分配)。另外象颖,使用無緩沖通道不會有任務在隊列中丟失或卡住佩厚,所有任務都會被處理。

注:以上是來自https://xueyuanjun.com/post/22061

實現(xiàn)下列實例:

// worker/worker.go

pcakge worker

import (
  "sync"
)

type Worker interface {
  Task()
}

type Pool struct {
  work chan Worker 
  wg sync.WaitGroup
}

func New(maxGoroutines int) *Pool {
  p := Pool {
      work:make(chan Worker),
 }

 p.wg.Add(maxGoroutines)
 for i := 0; i < maxGoroutines;i ++ {
    go func() {
        for w := range p.work {
          w.Task()
        }
        p.wg.Done()
    }()
    return &p
 }

func (p *Pool) Run (w Worker) {
  p.work <- w
}

func (p *Pool) ShutDown() {
  close(p.work)
  p.wg.Wait()
}
// main.go

package main

var langs = []string{
  "Golang",
  "PHP",
  "JavaScript"
  "Python",
  "Java",
}

type langPrinter struct {
  lang string
}

func (m *langPrinter) Task() {
  log.Println(m.lang)
  time.Sleep(time.Second)
}

func main() {
  var setnum = 3
  p := worker,New(3)
  var wg syn c.WaitGroup
  
  wg.Add(setnum * len(langs))
  for i := 0; i < setnum; i++ {
    lp := langPrinter{lang}
    go func() {
      p.Run(&lp)
      wg.Donw()
    }
  }
  wg.Wait()
  p.ShutDown()
}

以上是無緩存創(chuàng)建協(xié)程池
現(xiàn)在我會對緩存池進行深入分析说订!

先對 worker.go 進行分析抄瓦!

package worker

import (
    "sync"
)

// 創(chuàng)建公共的接口,這個接口是執(zhí)行任務邏輯的陶冷。
type Worker interface {
    Task()
}

// 協(xié)程池 struct
type Pool struct {
    work chan Worker 協(xié)程池
    wg sync.WaitGroup 原子容器
} 

// 實例化模塊方法钙姊!開辟協(xié)程池,任務傳遞的相關功能埂伦!
func New(maxGoroutines int) * Pool {
    // 開辟協(xié)程池煞额,對其進行實例化
    p := Pool{
        work:make(chan Worker),
    }

    // 添加原子計數(shù)器
    p.wg.Add(maxGoroutines)
        
        // 一次處理任務個數(shù),當 maxGoroutines = 3 沾谜。說明并發(fā)一次處理3個任務
    for i := 0; i < maxGoroutines; i++ {
        // 并發(fā)操作
        go func() {
            // 對 p.work (協(xié)程池) 進行遍歷膊毁,把所有任務進行分發(fā)!
           // 當 p.work 沒有任務的時候类早,會進行阻塞
            for w := range p.work {
                w.Task()
            }
                       
            // 對原子進行遞減
            p.wg.Done()
        }()
    }

    return &p
}

// 任務寫入方法媚媒!
func (p *Pool) Run (w Worker) {
    // 把任務寫入 p.work 的 chan 里面!
    p.work <- w
}

// 銷毀任務方法
func (p *Pool) ShutDown() {
    // 把 p.work 協(xié)程池進行銷毀
    close(p.work)
    // 等待所有 goroutine 執(zhí)行完畢
    p.wg.Wait()
}
package main

import (
    "golang_no_buff/worker"
    "log"
    "sync"
    "time"
)

var langs = []string{
    "Golang",
    "PHP",
    "JavaScript",
    "Python",
    "Java",
}

type langPrinter struct {
    lang string
}

// 對 langPrinter 綁定Task()方法涩僻,執(zhí)行 langPrinter 的任務邏輯操作缭召!
func (m *langPrinter) Task() {
    log.Println(m.lang)
    time.Sleep(time.Second)
}

func main() {
    // 所執(zhí)行任務數(shù)
    var setnum = 3
    p := worker.New(3)

    // 創(chuàng)建原子計數(shù)隊列
    var wg sync.WaitGroup
    // 添加原子數(shù)!3  * langs個數(shù)(5) = 15
    wg.Add(setnum * len(langs))

    // 對其循環(huán)3次
    for i := 0; i < setnum; i++ {
        // 循環(huán) 3 次 , 每一個 langs 有一個goroutine進行處理逆日,當 
        for _, lang := range langs {
            // 把 key 寫到 langPrinter 里面去
            lp := langPrinter{lang}
            // 對其實現(xiàn)并發(fā)操作
            go func() {
                // p.Run() 是把數(shù)據(jù)寫入 p.work 方法
                p.Run(&lp)
                // 對原子計數(shù)進行遞減
                wg.Done()
            }()
        }
    }

    // 等待所有線程執(zhí)行
    wg.Wait()
    // 把任務進行銷毀
    p.ShutDown()
}

上面基本邏輯我以注釋進行寫入嵌巷,里面原理需要自己體會!

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末室抽,一起剝皮案震驚了整個濱河市搪哪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坪圾,老刑警劉巖晓折,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惑朦,死亡現(xiàn)場離奇詭異,居然都是意外死亡漓概,警方通過查閱死者的電腦和手機漾月,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胃珍,“玉大人梁肿,你說我怎么就攤上這事∶僬茫” “怎么了吩蔑?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長填抬。 經(jīng)常有香客問我烛芬,道長,這世上最難降的妖魔是什么痴奏? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任蛀骇,我火速辦了婚禮,結果婚禮上读拆,老公的妹妹穿的比我還像新娘擅憔。我一直安慰自己,他們只是感情好檐晕,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布暑诸。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坯墨,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機與錄音西采,去河邊找鬼。 笑死继控,一個胖子當著我的面吹牛械馆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播武通,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼霹崎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了冶忱?” 一聲冷哼從身側響起尾菇,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后派诬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體劳淆,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年千埃,在試婚紗的時候發(fā)現(xiàn)自己被綠了憔儿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡放可,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出朝刊,到底是詐尸還是另有隱情耀里,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布拾氓,位于F島的核電站冯挎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏咙鞍。R本人自食惡果不足惜房官,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望续滋。 院中可真熱鬧翰守,春花似錦、人聲如沸疲酌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朗恳。三九已至湿颅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間粥诫,已是汗流浹背油航。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留怀浆,地道東北人谊囚。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像揉稚,于是被迫代替她去往敵國和親秒啦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359