转载地址:https://studygolang.com/articles/15477

使用Go语言实现并发的协程调度池阉割版,本文主要介绍协程池的基本设计思路,目的为深入浅出快速了解协程池工作原理,与真实的企业协程池还有很大差距,本文仅供学习参考。

一、何为并发,Go又是如何实现并发?

gopool1.jpeg

gopool2.jpeg

并行的好处:

  1. 同一时刻可以处理多个事务
  1. 更加节省时间,效率更高

具有并行处理能力的程序我们称之为“并发程序”

并发程序的处理能力优势体现在哪里?

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的协程池设计相关推荐

  1. 深入浅出 Golang 协程池设计

    使用Go语言实现并发的协程调度池阉割版,本文主要介绍协程池的基本设计思路,目的为深入浅出快速了解协程池工作原理,与真实的企业协程池还有很大差距,本文仅供学习参考. 一.何为并发,Go又是如何实现并发? ...

  2. golang协程池设计

    https://segmentfault.com/a/1190000018193161 Why Pool go自从出生就身带"高并发"的标签,其并发编程就是由groutine实现的 ...

  3. Go协程池设计思路(Task-Job-Worker)

    1. 铺垫:Go 的接收器Receiver 在go语言中,没有类的概念,但是可以给类型(结构体,自定义类型)定义方法.所谓方法就是定义了接受者的函数.接受者定义在func关键字和函数名之间.可以理解成 ...

  4. 白话 Golang 协程池

    文章目录 1.何为并发 2.并发的好处 3.Go 如何并发 4.G-P-M 调度模型 5.Go 程的代价 6.协程池的作用 7.简易协程池的设计&实现 8.开源协程池的使用 9.小结 参考文献 ...

  5. Golang并发模型:轻松入门协程池

    goroutine是非常轻量的,不会暂用太多资源,基本上有多少任务,我们可以开多少goroutine去处理.但有时候,我们还是想控制一下. 比如,我们有A.B两类工作,不想把太多资源花费在B类务上,而 ...

  6. Golang - 协程池 ants.NewPoolWithFunc使用介绍

    前言 ants是一个高性能的协程池,实现了对大规模goroutine的调度管理.goroutine复用,允许使用者在开发并发程序的时候限制协程数量,复用资源,达到更高效执行任务的效果. 提示:以下是本 ...

  7. Golang的协程调度器原理及GMP设计思想

    一.Golang"调度器"的由来? (1) 单进程时代不需要调度器 我们知道,一切的软件都是跑在操作系统上,真正用来干活(计算)的是CPU.早期的操作系统每个程序就是一个进程,知道 ...

  8. 一期每日一GO群分享-flag、viper、协程池、异常处理

    1.11 flag库 今天介绍一个库flag,命令行程序常用,用来接受参数的. var (intflag intboolflag boolstringflag string )func init() ...

  9. 连接池和协程池为何能提升并发能力?

    你有没有发现,"内存池"和"进程池"都带有"池"字?其实,这两种技术都属于"池化技术".它通常是由系统预先分配一批资源并 ...

最新文章

  1. 多个错误多个tryexcept的处理异常处理
  2. JPush 使用教程
  3. 因看不见而恐惧!企业亟需“看得见”威胁
  4. MySQL笔记3:深入理解MySQL中的NULL
  5. 强化学习笔记:Q-learning :temporal difference 方法
  6. jQuery easyUI--zTree属性菜单
  7. 突发!吴恩达确诊新冠,46岁生日还有不到3个月
  8. Python学习心得(二) : 更新列表
  9. VMware 11完全安装Mac OS X 10.10
  10. leetcode538. 把二叉搜索树转换为累加树
  11. 玩! 框架:为什么我会爱上它
  12. Kotlin plugin should be enabled before ‘kotlin-android-extensions‘
  13. python2 使用matplotlib
  14. Tomcat端口占用的处理方式
  15. lemon oa前端页面——由user-base-list谈项目组织
  16. 关于RNNLM的思考,特别是与HMM,n-gram的区别
  17. 【大数据】0001---使用SparkSQL关联两个表求和取前几行
  18. python基础 - 字符串与列表的基本操作方法
  19. 利用 USB转485通过Wireshark抓取MSTP数据
  20. 2021-02-09

热门文章

  1. WeakReference类详解
  2. cif文件服务器搭建,在linux下搭建NFS服务器实现文件共享
  3. mysql linux 数据库文件位置_mysql在linux下修改mysql数据库文件位置
  4. 排除MySQL中常见错误的实用招术
  5. 手机必备OCR文字识别软件:福昕扫描王使用攻略
  6. JavaScript Debug 之 Console
  7. 生成树协议(STP)原理与配置PVST+实现负载均衡
  8. 陈丽琳:如何以大数据助力商场运营
  9. 数字图像处理,图像锐化算法的C++实现
  10. 敏捷开发方法XP的12个最佳实践