go实现协程池管理
使用channel实现协程池
通过 Channel 实现 Goroutine Pool,缺点是会造成协程的频繁开辟和注销,但好在简单灵活通用。
package main
import (
"fmt"
"io/ioutil"
"net/http"
"sync"
)
// Pool goroutine Pool
type Pool struct {
queue chan int
wg *sync.WaitGroup
}
// New 新建一个协程池
func New(size int) *Pool {
if size <= 0 {
size = 1
}
return &Pool{
queue: make(chan int, size),
wg: &sync.WaitGroup{},
}
}
// Add 新增一个执行
func (p *Pool) Add(delta int) {
// delta为正数就添加
for i := 0; i < delta; i++ {
p.queue <- 1
}
// delta为负数就减少
for i := 0; i > delta; i-- {
<-p.queue
}
p.wg.Add(delta)
}
// Done 执行完成减一
func (p *Pool) Done() {
<-p.queue
p.wg.Done()
}
func (p *Pool) Wait() {
p.wg.Wait()
}
func main() {
// 这里限制100个并发
pool := New(100) // sync.WaitGroup{}
//假设需要发送1000万个http请求,然后我并发100个协程取完成这件事
for i := 0; i < 10000000; i++ {
pool.Add(1) //发现已存在100个人正在发了,那么就会卡住,直到有人完成了宣布自己退出协程了
go func(i int) {
resp, err := http.Get("https://www.baidu.com")
if err != nil {
fmt.Println(i, err)
} else {
defer resp.Body.Close()
result, _ := ioutil.ReadAll(resp.Body)
fmt.Println(i, string(result))
}
pool.Done()
}(i)
}
pool.Wait()
}
消费者模式实现协程池
频繁对协程开辟与剔除,如果对性能有着很高的要求,建议优化成固定数目的协程取 channel 里面取数据进行消费,这样可以避免协程的创建与注销。
package main
import (
"fmt"
"strconv"
"sync"
)
// 任务对象
type task struct {
Production
Consumer
}
// 设置消费者数目,也就是work pool大小
func (t *task) setConsumerPoolSize(poolSize int) {
t.Production.Jobs = make(chan *Job, poolSize*10)
t.Consumer.WorkPoolNum = poolSize
}
// 任务数据对象
type Job struct {
Data string
}
func NewTask(handler func(jobs chan *Job) (b bool)) (t *task) {
t = &task{
Production: Production{Jobs: make(chan *Job, 100)},
Consumer: Consumer{WorkPoolNum: 10, Handler: handler},
}
return
}
type Production struct {
Jobs chan *Job
}
func (c Production) AddData(data *Job) {
c.Jobs <- data
}
type Consumer struct {
WorkPoolNum int
Handler func(chan *Job) (b bool)
Wg sync.WaitGroup
}
// 异步开启多个work去处理任务,但是所有work执行完毕才会退出程序
func (c *Consumer) disposeData(data chan *Job) {
for i := 0; i <= c.WorkPoolNum; i++ {
c.Wg.Add(1)
go func() {
defer func() {
c.Wg.Done()
}()
c.Handler(data)
}()
}
c.Wg.Wait()
}
func main() {
// 实现一个用于处理数据的闭包,实现业务代码
consumerHandler := func(jobs chan *Job) (b bool) {
for jobs := range jobs {
fmt.Println(jobs)
}
return
}
// new一个任务处理对象
t := NewTask(consumerHandler)
t.setConsumerPoolSize(500) // 500个协程同时消费
// 根据自己的业务去生成数据通过AddData方法添加数据到生成channel,这里是100万条数据
go func() {
for i := 0; i < 1000000; i++ {
job := new(Job)
iStr := strconv.Itoa(i)
job.Data = "定义任务数据格式" + iStr
t.AddData(job)
}
}()
// 消费者消费数据
t.Consumer.disposeData(t.Production.Jobs)
}
go实现协程池管理的更多相关文章
- golang协程池设计
Why Pool go自从出生就身带“高并发”的标签,其并发编程就是由groutine实现的,因其消耗资源低,性能高效,开发成本低的特性而被广泛应用到各种场景,例如服务端开发中使用的HTTP服务,在g ...
- Unity协程(Coroutine)管理类——TaskManager工具分享
博客分类: Unity3D插件学习,工具分享 源码分析 Unity协程(Coroutine)管理类——TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处 ...
- fasthttp中的协程池实现
fasthttp中的协程池实现 协程池可以控制并行度,复用协程.fasthttp 比 net/http 效率高很多倍的重要原因,就是利用了协程池.实现并不复杂,我们可以参考他的设计,写出高性能的应用. ...
- 【爬虫小程序:爬取斗鱼所有房间信息】Xpath(协程池版)
# 本程序亲测有效,用于理解爬虫相关的基础知识,不足之处希望大家批评指正 from gevent import monkey monkey.patch_all() from gevent.pool i ...
- python 协程池和pool.map用法
一.问题描述 现在有一段代码,需要扫描一个网段内的ip地址,是否可以ping通. 执行起来效率太慢,需要使用协程. #!/usr/bin/env python # -*- coding: utf-8 ...
- python 并发编程 基于gevent模块 协程池 实现并发的套接字通信
基于协程池 实现并发的套接字通信 客户端: from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(('12 ...
- python 并发编程 协程池
协程池 from gevent.pool import Pool from gevent import monkey;monkey.patch_all() import gevent from gev ...
- python3下multiprocessing、threading和gevent性能对比----暨进程池、线程池和协程池性能对比
python3下multiprocessing.threading和gevent性能对比----暨进程池.线程池和协程池性能对比 标签: python3 / 线程池 / multiprocessi ...
- Golang协程池(workpool)实现
背景 因与工作相关,所以本文中的数据都进行了更改,但逻辑是一样的. 笔者的服务ServerA会请求服务ServerH获取一些数据,但ServerH的接口有个N秒内只能请求M次的限制,并返回false. ...
- golang协程池
type GoroutinePoll struct { Queue chan func() error Total, Num int Result chan error FinishCallBack ...
随机推荐
- Qt/C++地图动态绘制折线多边形矩形圆形标注点/可编辑拖动调整大小和位置
一.前言说明 无论哪一家的地图,都提供了调用函数绘制各种覆盖物,但是有时候的场景是希望进入添加覆盖物模式,然后每次在地图上按下都自动生成对应的覆盖物比如圆形,这样就不需要用户提前知道经纬度坐标等参数, ...
- Qt编写安防视频监控系统47-基本设置
一.前言 一个系统中肯定有不少的配置参数存储在配置文件中,配置文件可以是ini文件,也可以是json文件,还可以是自定义格式的文本文件,本人比较推荐ini文件,读写节点极其方便,支持中文内容,各种Qt ...
- Qt音视频开发21-通用硬解码
一.前言 硬件解码是图形芯片厂家提出的用GPU资源解码视频流的方案,与之相对的是软解,也就是传统的用CPU承担解码工作的方案:优点是效率高,功耗低.热功耗低,缺点是缺乏有力的支持(包括滤镜.字幕等), ...
- 概率论与数理统计教程(第二版,茆诗松,2010)PDF下载
概率论与数理统计教程(第二版,茆诗松,2010)PDF下载:共享地址
- 可扩展系统——基于SPI扩展
一.我们为什么讨论SPI? 为具有悠久历史的大型项目(屎山)添加新功能时,我们常常不太好评估变更的影响范围.因为原系统不具备良好的扩展性,导致修改整体发散,且不易单测.此时可以考虑使用接口来描述业务逻 ...
- Collection接口方法
Collection 接口继承树 Collection 接口Collection 接口是 List.Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 ...
- 对rpc长连接与短连接的思考
大家好,我是思无邪,某go中厂开发工程师,也是OSPP2024的学生参与者! 如果你觉得我的文章有帮助,记得三连支持一下哦! 目前正在深入研究源码,与你们一起进步,共同攻克编程难关! 欢迎关注我的公众 ...
- 掌握Python的hasattr()函数
掌握Python的hasattr()函数 在Python编程中,hasattr()函数是一个非常实用的内置函数,它允许我们动态地检查一个对象是否拥有某个属性.这个功能在编写灵活.可扩展的代码时尤为重要 ...
- Flink On Yarn的两种部署模式
一.内存Job管理模式yarn-per-job 使用介绍:常用的模式 二.内存集中管理模式yarn-session 使用介绍:当作业很少并且都较小,能快速执行完成时,可以使用.否则一般不会使用该模式 ...
- FLink12--KeyByReduceApp
一.依赖 参考博文:https://www.cnblogs.com/robots2/p/16048648.html 二.代码 package net.xdclass.class9; import ja ...