最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言協(xié)程池的實(shí)現(xiàn)示例

 更新時(shí)間:2025年09月26日 09:52:15   作者:fbbqt  
本文主要介紹了Go語言協(xié)程池的原理與實(shí)現(xiàn),通過限制goroutine數(shù)量避免性能下降,及通過AddTask和Run方法管理任務(wù)分配,確保并發(fā)控制,提升系統(tǒng)穩(wěn)定性,感興趣的可以了解一下

Go語言雖然有著高效的GMP調(diào)度模型,理論上支持成千上萬的goroutine,但是goroutine過多,對(duì)調(diào)度,gc以及系統(tǒng)內(nèi)存都會(huì)造成壓力,這樣會(huì)使我們的服務(wù)性能不升反降。常用做法可以用池化技術(shù),構(gòu)造一個(gè)協(xié)程池,把進(jìn)程中的協(xié)程控制在一定的數(shù)量,防止系統(tǒng)中goroutine過多,影響服務(wù)性能。

協(xié)程池模型

協(xié)程池簡(jiǎn)單理解就是有一個(gè)池子一樣的東西,里面裝有固定數(shù)量的goroutine,當(dāng)有一個(gè)任務(wù)到來的時(shí)候,會(huì)將這個(gè)任務(wù)交給池子里的一個(gè)空閑的goroutine去處理,如果池子里沒有空閑的goroutine了,任務(wù)就會(huì)阻塞等待。所以協(xié)程池有三個(gè)角色WorkerTask,Pool

屬性定義

  • Worker:用于執(zhí)行任務(wù)的goroutine
  • Task: 具體的任務(wù)
  • Pool: 池子

下面看一下各個(gè)角色的定義:

Task定義

Task有一個(gè)函數(shù)成員,表示這個(gè)task具體的執(zhí)行邏輯: 

type Task struct {
    f func() error  // 具體的執(zhí)行邏輯
}

Pool定義

  Pool有兩個(gè)成員,Capacity表示池子里的worker的數(shù)量,即工作的goroutine的數(shù)量,JobCh表示任務(wù)隊(duì)列用于存放任務(wù),goroutine從這個(gè)JobCh獲取任務(wù)執(zhí)行任務(wù)邏輯: 

type Pool struct {
    RunningWorkers int64     // 運(yùn)行著的worker數(shù)量
    Capacity       int64     // 協(xié)程池worker容量---goroutine數(shù)量
    JobCh          chan *Task // 用于worker取任務(wù)
    sync.Mutex
}

Worker 定義

// p為Pool對(duì)象指針
for task := range p.JobCh {
    do ...      
}

執(zhí)行任務(wù)單元,簡(jiǎn)單理解就是干活的goroutine,這個(gè)worker其實(shí)只做一件事情,就是不斷的從任務(wù)隊(duì)列里面取任務(wù)執(zhí)行,而worker的數(shù)量就是協(xié)程池里協(xié)程的數(shù)量,由Pool的參數(shù)指定。 

方法定義

NewTask用于創(chuàng)建一個(gè)任務(wù),參數(shù)是一個(gè)函數(shù),返回值是一個(gè)Task類型。

func NewTask(funcArg func() error) *Task

NewPool返回一個(gè)協(xié)程數(shù)量固定為Capacity協(xié)程池對(duì)象指針,其任務(wù)隊(duì)列的長(zhǎng)度為taskNum。 

func NewPool(Capacity int, taskNum int) *Pool

接下來主要介紹協(xié)程池的各個(gè)方法:

AddTask方法是往協(xié)程池添加任務(wù),如果當(dāng)前運(yùn)行著的worker數(shù)量小于協(xié)程池worker容量,則立即啟動(dòng)一個(gè)協(xié)程worker來處理任務(wù),否則將任務(wù)添加到任務(wù)隊(duì)列。 

func (p *Pool) AddTask(task *Task)

Run方法將協(xié)程池跑起來,啟動(dòng)一個(gè)worker來處理任務(wù)。 

func (p *Pool) Run()

協(xié)程池處理任務(wù)流程圖:

協(xié)程池實(shí)現(xiàn):

package main

import (
    "fmt"
    "sync"
    "sync/atomic"
    "time"
)

type Task struct {
    f func() error // 具體的任務(wù)邏輯
}

func NewTask(funcArg func() error) *Task {
    return &Task{
       f: funcArg,
    }
}

type Pool struct {
    RunningWorkers int64      // 運(yùn)行著的worker數(shù)量
    Capacity       int64      // 協(xié)程池worker容量
    JobCh          chan *Task // 用于worker取任務(wù)
    sync.Mutex
}

func NewPool(capacity int64, taskNum int) *Pool {
    return &Pool{
       Capacity: capacity,
       JobCh:    make(chan *Task, taskNum),
    }
}

func (p *Pool) GetCap() int64 {
    return p.Capacity
}

func (p *Pool) incRunning() { // runningWorkers + 1
    atomic.AddInt64(&p.RunningWorkers, 1)
}

func (p *Pool) decRunning() { // runningWorkers - 1
    atomic.AddInt64(&p.RunningWorkers, -1)
}

func (p *Pool) GetRunningWorkers() int64 {
    return atomic.LoadInt64(&p.RunningWorkers)
}

func (p *Pool) run() {
    p.incRunning()
    go func() {
       defer func() {
          p.decRunning()
       }()
       for task := range p.JobCh {
          task.f()
       }
    }()
}

// AddTask 往協(xié)程池添加任務(wù)
func (p *Pool) AddTask(task *Task) {
    // 加鎖防止啟動(dòng)多個(gè) worker
    p.Lock()
    defer p.Unlock()

    if p.GetRunningWorkers() < p.GetCap() { // 如果任務(wù)池滿, 則不再創(chuàng)建 worker
       // 創(chuàng)建啟動(dòng)一個(gè) worker
       p.run()
    }

    // 將任務(wù)推入隊(duì)列, 等待消費(fèi)
    p.JobCh <- task
}

func main() {
    // 創(chuàng)建任務(wù)池
    pool := NewPool(3, 10)

    for i := 0; i < 20; i++ {
       // 任務(wù)放入池中
       pool.AddTask(NewTask(func() error {
          fmt.Printf("I am Task\n")
          return nil
       }))
    }

    time.Sleep(1e9) // 等待執(zhí)行
}

 運(yùn)行結(jié)果:

I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task
I am Task

程序創(chuàng)建了一個(gè)Worker數(shù)量為3,任務(wù)隊(duì)列長(zhǎng)度為10的協(xié)程池,往里面添加了20個(gè)任務(wù),可以看到輸出,一直只有3個(gè)worker在做任務(wù),起到了控制goroutine數(shù)量的作用。

到此這篇關(guān)于Go語言協(xié)程池的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Go語言協(xié)程池內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang使用Gin框架實(shí)現(xiàn)HTTP響應(yīng)格式統(tǒng)一處理

    Golang使用Gin框架實(shí)現(xiàn)HTTP響應(yīng)格式統(tǒng)一處理

    在gin框架中,我們可以定義一個(gè)中間件來處理統(tǒng)一的HTTP響應(yīng)格式,本文主要為大家介紹了具體是怎么定義實(shí)現(xiàn)這樣的中間件的,感興趣的小伙伴可以了解一下
    2023-07-07
  • Go語言Zap庫Logger的定制化和封裝使用詳解

    Go語言Zap庫Logger的定制化和封裝使用詳解

    這篇文章主要介紹了Go語言Zap庫Logger的定制化和封裝使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Golang開發(fā)庫的集合及作用說明

    Golang開發(fā)庫的集合及作用說明

    這篇文章主要為大家介紹了Golang開發(fā)golang庫的集合及簡(jiǎn)單的作用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11
  • GoLang并發(fā)機(jī)制探究goroutine原理詳細(xì)講解

    GoLang并發(fā)機(jī)制探究goroutine原理詳細(xì)講解

    goroutine是Go語言提供的語言級(jí)別的輕量級(jí)線程,在我們需要使用并發(fā)時(shí),我們只需要通過 go 關(guān)鍵字來開啟 goroutine 即可。這篇文章主要介紹了GoLang并發(fā)機(jī)制goroutine原理,感興趣的可以了解一下
    2022-12-12
  • GO語言延遲函數(shù)defer用法分析

    GO語言延遲函數(shù)defer用法分析

    這篇文章主要介紹了GO語言延遲函數(shù)defer用法,較為詳細(xì)的分析了GO語言的特性與具體用法,并給出了一個(gè)比較典型的應(yīng)用實(shí)例,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-12-12
  • GO中Json解析的幾種方式

    GO中Json解析的幾種方式

    本文主要介紹了GO中Json解析的幾種方式,詳細(xì)的介紹了幾種方法,?文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • GoRoutines高性能同時(shí)進(jìn)行多個(gè)Api調(diào)用實(shí)現(xiàn)

    GoRoutines高性能同時(shí)進(jìn)行多個(gè)Api調(diào)用實(shí)現(xiàn)

    這篇文章主要為大家介紹了GoRoutines高性能同時(shí)進(jìn)行多個(gè)Api調(diào)用實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • go?smtp實(shí)現(xiàn)郵件發(fā)送示例詳解

    go?smtp實(shí)現(xiàn)郵件發(fā)送示例詳解

    這篇文章主要為大家介紹了go?smtp實(shí)現(xiàn)郵件發(fā)送示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • GO語言文件的創(chuàng)建與打開實(shí)例分析

    GO語言文件的創(chuàng)建與打開實(shí)例分析

    這篇文章主要介紹了GO語言文件的創(chuàng)建與打開的具體用法,實(shí)例分析了GO語言文件創(chuàng)建與打開操作中所涉及的函數(shù)具體用法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-12-12
  • Go語言實(shí)現(xiàn)二進(jìn)制與十進(jìn)制互轉(zhuǎn)的示例代碼

    Go語言實(shí)現(xiàn)二進(jìn)制與十進(jìn)制互轉(zhuǎn)的示例代碼

    這篇文章主要和大家詳細(xì)介紹了Go語言中實(shí)現(xiàn)二進(jìn)制與十進(jìn)制互相轉(zhuǎn)換的示例代碼,文中的代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-05-05

最新評(píng)論

贺州市| 临猗县| 鹤山市| 凉城县| 栾川县| 西充县| 义马市| 云安县| 东方市| 德昌县| 德昌县| 遵义县| 谷城县| 鹤岗市| 冷水江市| 辽源市| 宁武县| 红桥区| 望都县| 凤翔县| 临江市| 手游| 达尔| 荥阳市| 英超| 沂源县| 南和县| 治多县| 绥滨县| 黑河市| 莱芜市| 若尔盖县| 汤原县| 东源县| 合作市| 大安市| 阳高县| 杭锦后旗| 商水县| 新兴县| 安徽省|