Golang的协程池设计
转载地址:https://studygolang.com/articles/15477
使用Go语言实现并发的协程调度池阉割版,本文主要介绍协程池的基本设计思路,目的为深入浅出快速了解协程池工作原理,与真实的企业协程池还有很大差距,本文仅供学习参考。
一、何为并发,Go又是如何实现并发?
gopool1.jpeg
gopool2.jpeg
并行的好处:
- 同一时刻可以处理多个事务
- 更加节省时间,效率更高
具有并行处理能力的程序我们称之为“并发程序”
并发程序的处理能力优势体现在哪里?
goPool3.jpeg
二、Go语言如何实现并发?
package mainimport "fmt"
import "time"func go_worker(name string) {for i := 0; i < 10; i++ {fmt.Println("我是一个go协程, 我的名字是 ", name, "----")time.Sleep(1 * time.Second)}fmt.Println(name, " 执行完毕!")
}func main() {go go_worker("小黑") //创建一个goroutine协程去执行 go_worker("小黑")go go_worker("小白") //创建一个goroutine协程去执行 go_worker("小白")//防止main函数执行完毕,程序退出for {time.Sleep(1 * time.Second)}
}
那么多个goroutine之前如何通信呢?
package mainimport "fmt"func worker(c chan int) {//从channel中去读数据num := <-cfmt.Println("foo recv channel ", num)
}func main() {//创建一个channelc := make(chan int)go worker(c)//main协程 向一个channel中写数据c <- 1fmt.Println("send 1 -> channel over")
}
三、协程池的设计思路
为什么需要协程池?
虽然go语言在调度Goroutine已经优化的非常完成,并且Goroutine作为轻量级执行流程,也不需要CPU调度器的切换,我们一般在使用的时候,如果想处理一个分支流程,直接go
一下即可。
但是,如果无休止的开辟Goroutine依然会出现高频率的调度Groutine,那么依然会浪费很多上下文切换的资源,导致做无用功。所以设计一个Goroutine池限制Goroutine的开辟个数在大型并发场景还是必要的。
四、快速实现并发协程通讯池
gopool4.jpeg
package mainimport ("fmt""time"
)/* 有关Task任务相关定义及操作 */
//定义任务Task类型,每一个任务Task都可以抽象成一个函数
type Task struct {f func() error //一个无参的函数类型
}//通过NewTask来创建一个Task
func NewTask(f func() error) *Task {t := Task{f: f,}return &t
}//执行Task任务的方法
func (t *Task) Execute() {t.f() //调用任务所绑定的函数
}/* 有关协程池的定义及操作 */
//定义池类型
type Pool struct {//对外接收Task的入口EntryChannel chan *Task//协程池最大worker数量,限定Goroutine的个数worker_num int//协程池内部的任务就绪队列JobsChannel chan *Task
}//创建一个协程池
func NewPool(cap int) *Pool {p := Pool{EntryChannel: make(chan *Task),worker_num: cap,JobsChannel: make(chan *Task),}return &p
}//协程池创建一个worker并且开始工作
func (p *Pool) worker(work_ID int) {//worker不断的从JobsChannel内部任务队列中拿任务for task := range p.JobsChannel {//如果拿到任务,则执行task任务task.Execute()fmt.Println("worker ID ", work_ID, " 执行完毕任务")}
}//让协程池Pool开始工作
func (p *Pool) Run() {//1,首先根据协程池的worker数量限定,开启固定数量的Worker,// 每一个Worker用一个Goroutine承载for i := 0; i < p.worker_num; i++ {go p.worker(i)}//2, 从EntryChannel协程池入口取外界传递过来的任务// 并且将任务送进JobsChannel中for task := range p.EntryChannel {p.JobsChannel <- task}//3, 执行完毕需要关闭JobsChannelclose(p.JobsChannel)//4, 执行完毕需要关闭EntryChannelclose(p.EntryChannel)
}//主函数
func main() {//创建一个Taskt := NewTask(func() error {fmt.Println(time.Now())return nil})//创建一个协程池,最大开启3个协程workerp := NewPool(3)//开一个协程 不断的向 Pool 输送打印一条时间的task任务go func() {for {p.EntryChannel <- t}}()//启动协程池pp.Run()}
Golang的协程池设计相关推荐
- 深入浅出 Golang 协程池设计
使用Go语言实现并发的协程调度池阉割版,本文主要介绍协程池的基本设计思路,目的为深入浅出快速了解协程池工作原理,与真实的企业协程池还有很大差距,本文仅供学习参考. 一.何为并发,Go又是如何实现并发? ...
- golang协程池设计
https://segmentfault.com/a/1190000018193161 Why Pool go自从出生就身带"高并发"的标签,其并发编程就是由groutine实现的 ...
- Go协程池设计思路(Task-Job-Worker)
1. 铺垫:Go 的接收器Receiver 在go语言中,没有类的概念,但是可以给类型(结构体,自定义类型)定义方法.所谓方法就是定义了接受者的函数.接受者定义在func关键字和函数名之间.可以理解成 ...
- 白话 Golang 协程池
文章目录 1.何为并发 2.并发的好处 3.Go 如何并发 4.G-P-M 调度模型 5.Go 程的代价 6.协程池的作用 7.简易协程池的设计&实现 8.开源协程池的使用 9.小结 参考文献 ...
- Golang并发模型:轻松入门协程池
goroutine是非常轻量的,不会暂用太多资源,基本上有多少任务,我们可以开多少goroutine去处理.但有时候,我们还是想控制一下. 比如,我们有A.B两类工作,不想把太多资源花费在B类务上,而 ...
- Golang - 协程池 ants.NewPoolWithFunc使用介绍
前言 ants是一个高性能的协程池,实现了对大规模goroutine的调度管理.goroutine复用,允许使用者在开发并发程序的时候限制协程数量,复用资源,达到更高效执行任务的效果. 提示:以下是本 ...
- Golang的协程调度器原理及GMP设计思想
一.Golang"调度器"的由来? (1) 单进程时代不需要调度器 我们知道,一切的软件都是跑在操作系统上,真正用来干活(计算)的是CPU.早期的操作系统每个程序就是一个进程,知道 ...
- 一期每日一GO群分享-flag、viper、协程池、异常处理
1.11 flag库 今天介绍一个库flag,命令行程序常用,用来接受参数的. var (intflag intboolflag boolstringflag string )func init() ...
- 连接池和协程池为何能提升并发能力?
你有没有发现,"内存池"和"进程池"都带有"池"字?其实,这两种技术都属于"池化技术".它通常是由系统预先分配一批资源并 ...
最新文章
- 多个错误多个tryexcept的处理异常处理
- JPush 使用教程
- 因看不见而恐惧!企业亟需“看得见”威胁
- MySQL笔记3:深入理解MySQL中的NULL
- 强化学习笔记:Q-learning :temporal difference 方法
- jQuery easyUI--zTree属性菜单
- 突发!吴恩达确诊新冠,46岁生日还有不到3个月
- Python学习心得(二) : 更新列表
- VMware 11完全安装Mac OS X 10.10
- leetcode538. 把二叉搜索树转换为累加树
- 玩! 框架:为什么我会爱上它
- Kotlin plugin should be enabled before ‘kotlin-android-extensions‘
- python2 使用matplotlib
- Tomcat端口占用的处理方式
- lemon oa前端页面——由user-base-list谈项目组织
- 关于RNNLM的思考,特别是与HMM,n-gram的区别
- 【大数据】0001---使用SparkSQL关联两个表求和取前几行
- python基础 - 字符串与列表的基本操作方法
- 利用 USB转485通过Wireshark抓取MSTP数据
- 2021-02-09