用go语言实现一个有界协程池

写在文章开头

本篇文章算是对go语言系列的一个收尾,通过go语言实现一个实现一个简单的有界协程池。

在这里插入图片描述

Hi,我是 sharkChili ,是个不断在硬核技术上作死的 java coder ,是 CSDN的博客专家 ,也是开源项目 Java Guide 的维护者之一,熟悉 Java 也会一点 Go ,偶尔也会在 C源码 边缘徘徊。写过很多有意思的技术博客,也还在研究并输出技术的路上,希望我的文章对你有帮助,非常欢迎你关注我的公众号: 写代码的SharkChili

因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注 “加群” 即可和笔者和笔者的朋友们进行深入交流。

在这里插入图片描述

详解go语言协程池的实现

整体交互流程设计

我们希望创建一个协程池,该协程池大小由用户决定,主协程不断生产任务并投递到channel中,协程池收到任务后,如果发现没有对应处理的协程worker则创建一个协程并处理传入的任务,反之这些任务就会有序得等待协程有序调度执行:

在这里插入图片描述

定义worker

基于上图我们给出worker的接口定义,按照我们的实现每一个任务都是一个worker,协程池的协程可以从channel中得到对应的Worker 并执行其Task方法:

type Worker interface {
	Task()
}

声明协程池

基于worker我们封装一个worker池,也就是本文提到的协程池,可以看到该Pool有一个worker的通道用于存放主协程投递进来的任务,而wg则用于控制协程的生命周期,这一点我们会在后续的工作代码中详尽说明:

type Pool struct {
	//记录主协程投递的任务
	work chan Worker
	//控制工作协程的生命周期
	wg   sync.WaitGroup
}

创建协程池

有了协程池的定义之后,我们就可以编写协程池的,可以看到我们可以通过入参决定channel和协程的大小,通过传入maxGoroutines 设置wg的大小,当协程都没有任务执行时,才会调用wgDone方法,确保所有任务执行完成后,主协程才能退出:

func New(maxGoroutines int) *Pool {
	//创建指定协程数的channel
	p := Pool{
		work: make(chan Worker, maxGoroutines),
	}

	//基于协程数创建倒计时门闩
	p.wg.Add(maxGoroutines)

	//创建maxGoroutines个协程获取channel的任务执行
	for i := 0; i < maxGoroutines; i++ {

		go func() {
			for w := range p.work {
				w.DoTask()

			}
			//任务执行完成且channel关闭之后,按下倒计时门闩
			p.wg.Done()
		}()
	}
	
	//返回pool的指针
	return &p
}

投递任务

当我们需要投递任务时,就可以将自实现的worker投递到channle中:

func (p *Pool) Run(w Worker) {
	//将任务w投递到channel中
	p.work <- w
}

关闭协程池

最后我们给出关于协程池关闭的实现,其逻辑比较简单:

  1. 关闭channel不再接受新任务。
  2. 调用waitGroupWait方法等待所有协程执行完再返回。
func (p *Pool) ShutDown() {
	close(p.work)
	p.wg.Wait()
}

测试代码

最后我们给出本文的测试代码,使用示例比较简单:

  1. 定义一个姓名切片,作为测试数据。
  2. 创建一个名为namePrinter 的结构体,内部包含name属性,该结构体会继承Worker实现打印姓名的Task方法。
  3. 创建一个channel和协程大小都为2的Pool
  4. 通过多协程循环遍历name切片并将其封装成namePrinter投递到chanel中。
  5. 协程池的协程消费这些打印姓名的任务。
  6. 调用shutDown方法等待协程池内部协程工作完成后退出主协程。
// 创建一个测试用的姓名切片
var names = []string{
	"user.go-1",
	"user.go-2",
	"user.go-3",
	"user.go-4",
	"user.go-5",
}

// 实现worker接口 打印姓名
type namePrinter struct {
	name string
}

func (n *namePrinter) Task() {
	fmt.Println(n.name)
	time.Sleep(time.Second)
}

func main() {

	//创建还有两个协程的pool
	p := work.New(2)

	//创建main协程的倒计时门闩
	var wg sync.WaitGroup
	wg.Add(100 * len(names))

	//多协程投递任务到pool
	for i := 0; i < 100; i++ {

		for _, name := range names {
			np := namePrinter{
				name: name,
			}
			go func() {
				p.Run(&np)
				wg.Done()
			}()

		}
	}

	//等待任务投递完成
	wg.Wait()

	fmt.Println("执行结束,关闭pool")
	p.ShutDown()

}

小结

自此,本文基于go语言的并发技术实现了一个简单的协程池,希望对你有所帮助。而go语言系列也到此告一段落。

我是 sharkchiliCSDN Java 领域博客专家开源项目—JavaGuide contributor,我想写一些有意思的东西,希望对你有帮助,如果你想实时收到我写的硬核的文章也欢迎你关注我的公众号: 写代码的SharkChili
因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注 “加群” 即可和笔者和笔者的朋友们进行深入交流。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/648411.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AIGC时代算法工程师的面试秘籍(2024.4.29-5.12第十三式) |【三年面试五年模拟】

写在前面 【三年面试五年模拟】旨在整理&挖掘AI算法工程师在实习/校招/社招时所需的干货知识点与面试方法&#xff0c;力求让读者在获得心仪offer的同时&#xff0c;增强技术基本面。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&#x1f4aa; 欢迎大家关注Rocky…

引入安全生产培训云平台,实现“人人讲安全、个个会应急”

引入安全生产培训云平台&#xff0c;旨在全面提升企业及员工的安全意识与应急处理能力&#xff0c;通过数字化手段实现“人人讲安全、个个会应急”的目标。这一平台的构建和应用&#xff0c;不仅促进了安全知识的普及&#xff0c;还极大提高了培训的效率与效果。以下是该平台几…

Backend - postgresSQL DB 存储过程(数据库存储过程)

目录 一、存储过程的特性 &#xff08;一&#xff09;作用 &#xff08;二&#xff09;特点 &#xff08;三&#xff09;编码结构的区别 二、定时执行存储过程 三、2种编码结构 &#xff08;一&#xff09;函数结构 1. SQL代码 2. 举例 &#xff08;1&#xff09;例1-循…

邦之信短信分析:验证码短信、营销短信与通知短信的差异化解析

在数字通讯时代&#xff0c;短信已成为我们日常生活中不可或缺的一部分。其中&#xff0c;验证码短信、营销短信和通知短信各自扮演着不同的角色。今天&#xff0c;飞鸽将带您深入了解这三种短信类型之间的核心差异。 1. 验证码短信 验证码短信广泛应用于各类电商网站和…

【UE5.1 角色练习】07-AOE技能

目录 效果 步骤 一、准备技能动画 二、准备粒子特效 三、技能蓝图 四、相机震动 前言 在上一篇&#xff08;【UE5.1 角色练习】06-角色发射火球-part2&#xff09;基础上继续实现角色释放AOE技能的功能。 效果 步骤 一、准备技能动画 1. 在项目设置中添加一个操作映…

如何恢复已删除/丢失的照片/视频?

“嗨&#xff0c;我把我所有的世界杯照片和视频都存储在我的数码相机存储卡上。但是&#xff0c;当我将存储卡与计算机连接时&#xff0c;它会要求我格式化存储卡。我格式化了存储卡&#xff0c;但我所有的世界杯照片和视频都不见了。这对我来说是一场大灾难。是否有可能恢复丢…

[图解]产品经理创新模式01物流变成信息流

1 00:00:01,570 --> 00:00:04,120 有了现状的业务序列图 2 00:00:04,960 --> 00:00:08,490 我们就来改进我们的业务序列图了 3 00:00:08,580 --> 00:00:11,010 把我们要做的系统放进去&#xff0c;改进它 4 00:00:13,470 --> 00:00:15,260 怎么改进&#xff1f;…

【MATLAB】信号的熵

近似熵、样本熵、模糊熵、排列熵|、功率谱熵、奇异谱熵、能量熵、包络熵 代码内容&#xff1a; 获取代码请关注MATLAB科研小白的个人公众号&#xff08;即文章下方二维码&#xff09;&#xff0c;并回复信号的熵本公众号致力于解决找代码难&#xff0c;写代码怵。各位有什么急需…

Pytorch DDP分布式细节分享

自动微分和autograde 自动微分 机器学习/深度学习关键部分之一&#xff1a;反向传播&#xff0c;通过计算微分更新参数值。 自动微分的精髓在于它发现了微分计算的本质&#xff1a;微分计算就是一系列有限的可微算子的组合。 自动微分以链式法则为基础&#xff0c;依据运算逻…

Tomcat源码解析(七):底层如何获取请求url、请求头、json数据?

Tomcat源码系列文章 Tomcat源码解析(一)&#xff1a;Tomcat整体架构 Tomcat源码解析(二)&#xff1a;Bootstrap和Catalina Tomcat源码解析(三)&#xff1a;LifeCycle生命周期管理 Tomcat源码解析(四)&#xff1a;StandardServer和StandardService Tomcat源码解析(五)&…

知攻善防应急响应靶机训练-Web3

前言 本次应急响应靶机采用的是知攻善防实验室的Web-3应急响应靶机 靶机下载地址为&#xff1a; https://pan.quark.cn/s/4b6dffd0c51a 相关账户密码 用户:administrator 密码:xj123456xj123456 解题过程 第一题-攻击者的两个IP地址 直接查看apache的log日志搜索.php 发现…

学习Uni-app开发小程序Day26

这一章学习的内容细节较多&#xff0c;主要是分为&#xff1a;首次加载减少网络消耗、获取图片的详细信息、图片的评分和避免重复评分、将图片下载到本地并且获取设备的授权 加载图片减少网络消耗 这里突出这个功能&#xff0c;是根据老师视频上的描述&#xff0c;个人觉得很…

Spark介绍

Spark简介 Spark,是一种通用的大数据计算框架,正如传统大数据技术Hadoop的MapReduce、Hive引擎,以及Storm流式实时计算引擎等. Spark是加州大学伯克利分校AMP实验室(Algorithms Machines and People Lab)开发的通用内存并行计算框架,用于构建大型的、低延迟的数据分析应用程序…

Python图像处理库全面详细解析

目录 引言 PIL和Pillow&#xff1a;基础但强大的图像处理 PIL到Pillow的演变 功能亮点 实际应用案例 Pillow的适用场景 结论 ​编辑 OpenCV&#xff1a;计算机视觉的瑞士军刀 OpenCV的核心特点 功能亮点 实际应用案例 OpenCV的适用场景 结论 ​编辑 Scikit-Imag…

pytest:指定测试用例执行顺序

在自动化测试中&#xff0c;测试用例的执行顺序有时对测试结果具有重要影响。本文将介绍如何在pytest框架中使用pytest-ordering插件以及Collection hooks来控制测试用例的执行顺序。 方式1&#xff1a; 使用pytest-ordering插件控制执行顺序 1.1 安装pytest-ordering插件 首…

Python编程的黑暗魔法:模块与包的神秘力量!

哈喽&#xff0c;我是阿佑&#xff0c;今天给大家讲讲模块与包~ 文章目录 1. 引言1.1 模块化编程的意义1.2 Python中模块与包的概念概述 2. 背景介绍2.1 Python模块系统模块的定义与作用Python标准库简介 2.2 包的结构与目的包的定义与目录结构包在项目组织中的重要性 3. 创建与…

用three.js+echarts给公司写了一个站点数据大屏系统经验总结

时间过的好快,参加公司的新项目研发快一年了,五一机器人项目首秀,我们遇到了高并发集中下单情景,然后海量数据处理场景来了,给我在后端领域的高并发实践业务上画上了漂亮的一笔经验。人都是在磨练中成长,我很感谢这次给我的机会,虽然有点累,但也有点小成就。正好现在有…

基于RK3568核心板的雷视融合一体机,助力交通管理智能化升级

随着5G网络与智慧交通车路协同系统在全国各点的落地&#xff0c;作为提升交通安全的前沿技术方案也愈发受到重视。 在交通信控领域&#xff0c;以往的感知技术、无论是地磁、线圈还是摄像头&#xff0c;功能都仅仅局限于数清经过了多少车辆&#xff0c;无法满足交通数字化管理…

aosp14的分屏接口ISplitScreen接口获取方式更新-学员疑问答疑

背景&#xff1a; 有学员朋友在学习马哥的分屏pip自由窗口专题时候&#xff0c;做相关分屏做小桌面项目时候&#xff0c;因为原来课程版本是基于android 13进行的讲解的&#xff0c;但是现在公司已经开始逐渐进行相关的android 14的适配了&#xff0c;但是android 14这块相比a…

挖矿宝藏之系统日志

什么是日志&#xff1f; 日志是指系统或应用程序在运行过程中产生的记录文件&#xff0c;这些文件记录了系统或应用程序的运行情况、错误信息、用户操作等。 日志的主要作用 记录信息&#xff1a;日志可以记录系统或应用程序的启动、运行、停止等状态信息&#xff0c;以及用户的…