golang 实现协程池

go 的 goroutine 提供了一种比线程而言更廉价的方式处理并发场景。相比线程,协程占据更小的内存空间,并且由于是在用户态进行调度,上下文切换的代价更小。所以协程更加容易支撑几万几百万的并发。但 goroutine 太多仍会导致调度性能下降、GC 频繁、内存暴涨, 引发一系列问题。

因此本文的目的是学习如何实现一个go协程池。
借鉴java的线程池,定义如下的结构体

type GoroutinePool struct {name     stringcoreSize uint32 //定义有多少协程taskChan chan func() //类似java的Runable中的run方法stop     bool //是否停止协程池
}

新建一个协程池,通过start方法启动协程。
使用select实现任务的执行和协程的销毁

func NewGoroutinePool(name string, coreSize uint32) *GoroutinePool{goroutinePool := &GoroutinePool{name:     name,coreSize: coreSize,taskChan: make(chan func()),stop:     false,}goroutinePool.start()return goroutinePool
}func (pool *GoroutinePool) start() {for i := uint32(0); i < pool.coreSize; i++ {go func() {for {select {case task := <-pool.taskChan:task()default:if pool.stop && len(pool.taskChan) == 0{log.Printf("stop")close(pool.taskChan)break}}}}()}
}

提交任务并且执行,使用go的recover()机制,避免panic导致协程终止

func (pool *GoroutinePool) Execute(tasks ...Task) error {if pool.stop {return fmt.Errorf("pool is stop")}for _, t := range tasks {task := tfun := func() { pool.exec(task) }pool.taskChan <- fun}return nil
}func (pool *GoroutinePool) exec(task Task) {defer func() {if err := recover(); err != nil {stacks := pool.getStacks(5, 6)log.Printf("%s pool exec panic:%v,stack:%v", pool.name, err, stacks)}}()result, err := task()log.Printf("result:%v,err:%v", result, err)
}

停止协程、执行异常时获取堆栈信息

func (pool *GoroutinePool) Stop() {pool.stop = true
}func (pool *GoroutinePool) getStacks(skip int, maxNum int) []string {pc := make([]uintptr, maxNum)n := runtime.Callers(skip, pc)var stacks []stringfor i := 0; i < n; i++ {f := runtime.FuncForPC(pc[i])if f == nil {stacks = append(stacks, "unknown Func")} else {file, line := f.FileLine(pc[i])stacks = append(stacks, fmt.Sprintf("%v %v %v", f.Name(), file, line))}}return stacks
}

可以看出利用golang的go语法糖和channel机制可以很容易的实现一个协程池。
但是本文实现的协程池还缺少了:

1、协程池大小的动态扩展能力;例如java支持coreSzie和maxSize,允许一定的突发。

2、拒绝策略。

3、使用pool.taskChan <- fun 进行任务的提交,当channel满时,会阻塞业务逻辑。

推荐阅读

1、原来阿里字节员工简历长这样

2、一条SQL差点引发离职

3、MySQL并发插入导致死锁


如果你也觉得我的分享有价值,记得点赞或者收藏哦!你的鼓励与支持,会让我更有动力写出更好的文章哦!

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

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

相关文章

【搞懂设计模式】命令模式:从遥控器到编程的妙用!

我们都熟悉电视遥控器&#xff0c;它有许多按钮&#xff0c;每个按钮都有确定的功能。你按下电源键电视就会打开&#xff0c;再按下一次电视就会关闭。编程世界里也有这种模式&#xff0c;这就是我们说的命令模式。 命令模式是一种设计模式&#xff0c;它把一个请求或操作封装…

以梦为码,CodeArts Snap 缩短我与算法的距离

背景 最近一直在体验华为云的 CodeArts Snap&#xff0c;逐渐掌握了使用方法&#xff0c;代码自动生成的准确程度大大提高了。 自从上次跟着 CodeArts Snap 学习用 Python 编程&#xff0c;逐渐喜欢上了 Python。 我还给 CodeArts Snap 起了一个花名&#xff1a; 最佳智能学…

千问 qwen7B 微调后的模型推理代码

watch -n 1 nvidia-smi 1、数据处理代码 import asttrain_dataset []# 定义合法的字段列表 valid_fields ["id", "conversations"]with open(train.json, r, encoding"utf-8") as f:train_data f.readlines() for i, item in enumerate(tra…

计算机服务器中了halo勒索病毒怎么办,halo勒索病毒解密处理流程

计算机技术的发展与应用为企业的生产生活提供了坚实基础&#xff0c;但同时也为网络安全威胁制造了有利条件。近期&#xff0c;网络上的勒索病毒非常嚣张&#xff0c;给企业的计算机服务器带来严重威胁。近日&#xff0c;云天数据恢复中心接到山东某制造公司的求助&#xff0c;…

Oracle DG环境下的秘钥管理

今天有朋友问到1&#xff09;DG环境下的秘钥管理需要注意什么&#xff0c;2&#xff09;秘钥管理对DG的日志同步有影响吗&#xff1f; 对于2&#xff09;的回答是明确的&#xff0c;没有影响。秘钥的管理和DG的redo log shipping完全是两套机制。在最新版的Oracle Key Vault常…

Qlik Sense : ErrorCode(错误变量)

错误变量 所有错误变量的值在脚本执行之后依然保留。第一个变量 ErrorMode 由用户输入&#xff0c;最后三个变量是 Qlik Sense 的输出&#xff08;包括脚本中错误的信息&#xff09;。 使用每个变量的下拉列表可查看每个变量的简短描述和语法。单击语法描述中的变量名称可了解…

Vulnhub靶机:FunBox10

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;FunBox10&#xff08;10.0.2.35&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://download.vulnhub.com/funbo…

Effective C++——关于重载赋值运算

令operator返回一个*this的引用 在重载,,*等运算符时&#xff0c;令其返回一个指向this的引用。 class MyClass {int* val; public:MyClass(int i) : val(new int(i)){}MyClass():val(new int(0)){}void print() {cout << *val << endl;}MyClass& operator(co…

mysql面试题合集-基础

前言 工作很忙&#xff0c;本质还是自己比较懒惰&#xff0c;很久没更新博客了。近期打算面试&#xff0c;换个工作环境&#xff0c;那就先从面试题开始吧&#xff0c;后续也会逐渐更新自己在工作中的一些经验感悟。接下来切入主题&#xff0c;由于长期做前台开发工作&#xf…

LabVIEW电液比例阀测试系统

电液比例阀与普通阀和伺服阀相比&#xff0c;比例阀展现出显著的耐污染和可靠性特点。为了满足这些比例阀的综合性能测试需求&#xff0c;开发了一种基于LabVIEW软件的电液比例阀综合性能试验台。这个系统不仅能够进行比例压力阀、流量阀和方向阀的性能测试&#xff0c;而且通过…

RabbitMQ 笔记一

概览&#xff1a; MQ基本概念 RabbitMQ入门 基本工作模 1.MQ是什么&#xff1f; MQ:Message Queue, 存储消息的中间件&#xff0c;是消息发送过程中的暂存容器&#xff0c;主要用于解决分布式系统进程间的通信。 分布式系统通信的两种方式&#xff1a;直接远程调用、借助第三…

01:云计算底层技术奥秘|虚拟化管理|公有云概述

云计算底层技术奥秘&#xff5c;虚拟化管理&#xff5c;公有云概述 虚拟化平台安装验证虚拟化支持 Linux虚拟机创建虚拟机磁盘虚拟机配置文件创建虚拟机 公有云简介 虚拟化平台安装 虚拟化&#xff1a;是一种技术 就是将不可拆分的实体资源变成可以自由划分的逻辑资源&#xf…

one-stage/two-stage区别

One-stage和Two-stage是目标检测中的两种主要方法&#xff0c;它们在处理速度和准确性上存在显著差异。以下是两者的主要区别&#xff1a; 处理流程&#xff1a;One-stage方法通过卷积神经网络直接提取特征&#xff0c;并预测目标的分类与定位&#xff0c;一步到位&#xff0c…

【数据库学习】PostgreSQL优化

1&#xff0c;数据库减负思路 缓存 页面静态化 实时性不高的数据&#xff1b;数据库优化sql优化 表结构优化 数据库分区分表 合并数据库操作&#xff0c;将多次操作合并成一条sql执行。热点数据分离 主表只保存活跃数据。数据库读写分离 2&#xff0c;执行计划 explain只…

美易官方:Edward Jones将特斯拉评级从买进下调至持有

近日&#xff0c;知名金融机构Edward Jones宣布将对特斯拉&#xff08;Tesla&#xff09;的评级进行调整&#xff0c;从买进下调至持有。这一消息引起了市场的广泛关注。特斯拉作为全球领先的电动汽车制造商&#xff0c;其股票一直备受投资者关注。本文将对此次评级调整进行分析…

【Go学习】Ginkgo测试框架学习实践 + 问题记录 + 怎么解决(0)

1、ginkgo测试框架介绍&#xff1a;https://onsi.github.io/ginkgo/ 2、重点是学习实践 问题记录 怎么解决 3、送福利&#xff1a;国内好用的ChatGpt有很多&#xff0c;比如&#xff1a;天工、文心一言、讯飞星火、通义万相等 1. 安装 xxxmacdeMacBook-Pro-3  /Volumes/mac…

【JS基础】定时器的使用、事件监听

文章目录 前言一、定时器1.1定时器是什么1.2 setInterval函数1.3 关闭定时器clearInterval 二、事件监听2.1 事件监听是什么2.2 事件监听的使用基本语法点击事件鼠标事件焦点事件键盘事件 2.3 事件对象event 总结 前言 JavaScript 中的定时器和事件监听是 Web 开发中至关重要的…

leetcode hot100组合

在本题中&#xff0c;是要求返回[1,n]这个数组的长度为k的组合。涉及到排列、组合、棋盘、分割等问题的时候&#xff0c;要考虑利用回溯来进行解决。 回溯和递归类似&#xff0c;也分为三步进行分析 确定递归函数的返回值和参数&#xff1a;一般来说返回值都是void&#xff0c…

黑豹程序员-vue实现两级联动下拉列表

需求 在开发中这类需求很多&#xff0c;前后两个下拉框有紧密关系&#xff0c;第一个下拉框相当于一个分类&#xff0c;选中第一个下拉框中的某个分类后&#xff0c;第二个下拉框的内容随之改变&#xff0c;列出其分类下的选项。 图例 选中某个一级风险领域后&#xff0c;二级…

在学校中,N个小朋友站成一队, 第i个小朋友的身高为height[i],,单调栈的应用

在学校中&#xff0c;N个小朋友站成一队&#xff0c; 第i个小朋友的身高为height[i]&#xff0c; 第i个小朋友可以看到的第一个比自己身高更高的小朋友j&#xff0c;那么j是i的好朋友(要求j > i)。 请重新生成一个列表&#xff0c;对应位置的输出是每个小朋友的好朋友位置&a…