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

news2024/11/17 4:43:59

写在文章开头

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C语言】自定义类型:联合与枚举的简明概述

&#x1f525;引言 关于自定义类型除了我们常用的结构体&#xff0c;还有联合与枚举也是属于自定义类型。本篇将简单介绍联合与枚举基本概念和使用方法 &#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&…

中国改革报是什么级别的报刊?在哪些领域具有较高的影响力?

中国改革报是什么级别的报刊&#xff1f;在哪些领域具有较高的影响力&#xff1f; 《中国改革报》是国家发展和改革委员会主管的全国性综合类报纸。它在经济领域和改革发展方面具有重要的影响力&#xff0c;是传递国家政策、反映改革动态的重要平台。该报对于推动中国的经济改…

【Java限流算法详解及实现】

Java限流算法详解及实现 在高并发场景下&#xff0c;限流是保护系统的重要手段。限流算法可以帮助我们在流量过大时进行合理的控制&#xff0c;避免系统崩溃。本文将详细介绍几种常见的限流算法及其在Java中的实现。 Java限流算法详解及实现 Java限流算法详解及实现一、令牌桶…

Android 深入系统源码探讨 Activity、Window 和 View 的关系与实践

文章目录 1、概括2、Android Window 设计2.1、Window 类2.2、PhoneWindow2.3、WindowManager2.4、ViewRootImpl2.5、DecorView 3、Android Activity 设计3.1、Activity的基本概念3.2.、Activity的生命周期3.3、Activity的内部结构 4、Android View 设计4.1、View的基本概念4.2、…

构建智慧城市公共服务系统的功能架构设计

随着城市化进程的加速&#xff0c;城市公共服务系统在保障居民生活品质、提升城市管理水平方面扮演着愈发重要的角色。构建智慧城市公共服务系统的功能架构设计至关重要&#xff0c;它不仅需要充分考虑居民需求与城市管理的实际情况&#xff0c;还需要整合先进的科技手段&#…

vue3快速入门(局部使用)

目录 前置知识JavaScript-导入导出 入门操作 变量渲染页面 局部使用vue的实现步骤 vue指令 v-for v-bind v-if v-show v-on v-model 生命周期 前置知识JavaScript-导入导出 正常情况在html导入js文件是全部导入&#xff0c;这样会导致性能上的损失 。 JS提供的…

Docker之xfs文件系统下安装报错解决方案

一、需求说明 centos系统下安装docker最新版的时候&#xff0c;安装成功&#xff0c;启动的时候报错。报错信息“failed to start daemon: error initializing graphdriver: overlay2: the backing xfs filesystem is formatted without d_type support, which leads to incorr…

5.26机器人基础-DH参数 正解

1.建立DH坐标系 1.确定Zi轴&#xff08;关节轴&#xff09; 2.确定基础坐标系 3.确定Xi方向&#xff08;垂直于zi和zi1的平面&#xff09; 4.完全确定各个坐标系 例子&#xff1a; 坐标系的布局是由个人决定的&#xff0c;可以有不同的选择 标准坐标系布局&#xff1a; …

NDIS协议驱动(一)

Microsoft Windows 操作系统使用基于 1978 年国际标准化组织 (ISO) 开发的七层网络模型的网络体系结构。 ISO 开放系统互连 (OSI) 参考模型将网络描述为“一系列协议层&#xff0c;具有分配给每个层的一组特定函数。 每个层都向更高层提供特定的服务&#xff0c;同时阻止这些层…

vscode:如何解决”检测到include错误,请更新includePath“

vscode:如何解决”检测到include错误&#xff0c;请更新includePath“ 前言解决办法1 获取includePath路径2 将includePath路径添加到指定文件3 保存 前言 配置vscode是出现如下错误&#xff1a; 解决办法 1 获取includePath路径 通过cmd打开终端&#xff0c;输入如下指令&a…

有个小伙把 MyBatis 替换成 MyBatis-Plus,上线后就被开了!!

MyBatis-Plus 替换 MyBatis 首先&#xff0c;我们准备了一张名为 tbl_order 的表&#xff0c;并初始化了其中的两条数据。 DROP TABLE IF EXISTS tbl_order; CREATE TABLE tbl_order (id bigint(0) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 自增主键,order_no varchar(50)…

云易办springboot+vue后端

springbootvue云易办后端项目完成 一.创建项目 创建父项目&#xff1a;yeb&#xff0c; 使用spring Initializr&#xff0c;完成创建之后删除无用文件夹&#xff0c;作为父项目 添加packaging <packaging>pom</packaging>二.创建子模块&#xff1a;yeb-server …

这或许是国产游戏出海的最佳时机

《刺客信条&#xff1a;影》过于政治正确的选角激怒了全球玩家&#xff0c;而社交媒体上有玩家讨论育碧是否应该因为刻意加入DEI&#xff08;多元化&#xff09;而延期《刺客信条&#xff1a;影》时&#xff0c;没想到这得到了X拥有人埃隆马斯克的回复。马斯克表示“DEI&#x…

内网穿透实现公网访问自己搭建的Ollma架构的AI服务器

内网穿透实现公网访问自己搭建的Ollma架构的AI服务器 [2024年5月9号我发布一个博文关于搭建本地AI服务器的博文][https://blog.csdn.net/weixin_41905135/article/details/138588043?spm1001.2014.3001.5501]&#xff0c;今天我们内网穿透实现从公网访问我的本地AI服务器&…

【深度学习】最强算法之:人工神经网络(ANN)

人工神经网络ANN 1、引言2、人工神经网络(ANN)2.1 定义2.1.1 定义2.1.2 应用场景 2.2 核心原理2.3 实现方式2.4 算法公式2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;看新闻没&#xff1f; 小鱼&#xff1a;新闻天天看&#xff0c;啥事大惊小怪的。 小屌…

C++干货 --类和对象(二)

前言&#xff1a; 上文中&#xff0c;我们介绍了类这一重要知识点&#xff0c;包括为什么要有类、类的使用方法、封装、以及对象实例化。详情可以去看我的文章&#xff1a;写文章-CSDN创作中心C干货 --类和对象(一)-CSDN博客写文章-CSDN创作中心 这篇文章&#xff0c;我们简单…

全球点赞最高的人颜廷利:真正的人生目标是什么

在那个充满生机的2024年春天&#xff0c;记者有幸对中国第一起名大师的老师颜廷利教授进行了深入的访谈。带着对其人生哲学的强烈好奇&#xff0c;记者紧张而期待地提出了问题&#xff1a;“颜教授&#xff0c;您在漫长的人生旅途中最追求的是什么&#xff1f;” 宁夏银川、山东…

【模拟面试问答】深入解析力扣163题:缺失的区间(线性扫描与双指针法详解)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

文盘Rust -- 生命周期问题引发的 static hashmap 锁

100编程书屋_孔夫子旧书网 2021年上半年,撸了个rust cli开发的框架,基本上把交互模式,子命令提示这些cli该有的常用功能做进去了。项目地址:https://github.com/jiashiwen/interactcli-rs。 春节以前看到axum已经0.4.x了,于是想看看能不能用rust做个服务端的框架。 春节…

C++的哈希 哈希表 哈希桶

目录 Unordered系列关联式容器 什么是哈希 哈希表 闭散列 载荷因子α 扩容 查找 删除 字符串哈希算法 最终代码 开散列 插入 查找 删除 最终代码 完整代码 Unordered系列关联式容器 C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0…