使用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实现协程池管理的更多相关文章

  1. golang协程池设计

    Why Pool go自从出生就身带“高并发”的标签,其并发编程就是由groutine实现的,因其消耗资源低,性能高效,开发成本低的特性而被广泛应用到各种场景,例如服务端开发中使用的HTTP服务,在g ...

  2. Unity协程(Coroutine)管理类——TaskManager工具分享

    博客分类: Unity3D插件学习,工具分享 源码分析   Unity协程(Coroutine)管理类——TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处 ...

  3. fasthttp中的协程池实现

    fasthttp中的协程池实现 协程池可以控制并行度,复用协程.fasthttp 比 net/http 效率高很多倍的重要原因,就是利用了协程池.实现并不复杂,我们可以参考他的设计,写出高性能的应用. ...

  4. 【爬虫小程序:爬取斗鱼所有房间信息】Xpath(协程池版)

    # 本程序亲测有效,用于理解爬虫相关的基础知识,不足之处希望大家批评指正 from gevent import monkey monkey.patch_all() from gevent.pool i ...

  5. python 协程池和pool.map用法

    一.问题描述 现在有一段代码,需要扫描一个网段内的ip地址,是否可以ping通. 执行起来效率太慢,需要使用协程. #!/usr/bin/env python # -*- coding: utf-8 ...

  6. python 并发编程 基于gevent模块 协程池 实现并发的套接字通信

    基于协程池 实现并发的套接字通信 客户端: from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(('12 ...

  7. python 并发编程 协程池

    协程池 from gevent.pool import Pool from gevent import monkey;monkey.patch_all() import gevent from gev ...

  8. python3下multiprocessing、threading和gevent性能对比----暨进程池、线程池和协程池性能对比

    python3下multiprocessing.threading和gevent性能对比----暨进程池.线程池和协程池性能对比   标签: python3 / 线程池 / multiprocessi ...

  9. Golang协程池(workpool)实现

    背景 因与工作相关,所以本文中的数据都进行了更改,但逻辑是一样的. 笔者的服务ServerA会请求服务ServerH获取一些数据,但ServerH的接口有个N秒内只能请求M次的限制,并返回false. ...

  10. golang协程池

    type GoroutinePoll struct { Queue chan func() error Total, Num int Result chan error FinishCallBack ...

随机推荐

  1. Scoop: 开发者多环境管理利器

    Scoop是什么? Scoop 是一个基于 Windows 的包管理器,能够帮助开发者高效管理开发环境和应用程序. 它推荐通过命令行进行包的安装.更新和卸载,同时提供了简单易用的包组织方式,透明化了安 ...

  2. Qt编写物联网管理平台33-设备面板

    一.前言 设备面板展示数据,相对于表格展示,可能在一个页面中能够展示的设备数据量少一些,但是有些用户和场景,又需要这种面板的形式,可能更生动形象一些.尤其是经过这么些年的社会的毒打,我的原则是:用户是 ...

  3. 在C++中实现委托事件的方法

    参考链接: 1.在C++中模拟委托事件的方法(一) 2.利用C++的模板模拟.net的代理语法 源码学习: 1.https://pan.baidu.com/s/15vbryvzDnvmJ6FMku6_ ...

  4. 前端(二)-CSS

    1.样式 1.1 行内样式 <h1 style="color:red;">行内样式</h1> 1.2 内部样式 CSS代码写在 <head> 的 ...

  5. Elasticsearch-总结列表

    1.lucene基本概念 目前以 Lucene 为基础建立的开源可用全文搜索引擎主要是 Solr 和 Elasticsearch. Solr 和 Elasticsearch 都是比较成熟的全文搜索引擎 ...

  6. [rustGUI][iced]基于rust的GUI库iced(0.13)的部件学习(04):实现窗口主题(颜色)变换(暨menu菜单的使用)

    前言 本文是关于iced库的部件介绍,iced库是基于rust的GUI库,作者自述是受Elm启发. iced目前的版本是0.13.1,相较于此前的0.12版本,有较大改动. 本合集是基于新版本的关于分 ...

  7. Object类是所有Java类的根父类

  8. 载誉而归!天翼云荣获第23届中国IT用户满意度大会多项殊荣

    10月25日,2024第23届中国IT用户满意度大会暨首届工业产品满意度交流会在北京举行.现场揭晓"2024中国IT用户满意度征集结果",天翼云凭借领先的产品技术.完善的客户服务以 ...

  9. 天翼云边缘安全加速平台亮相2023亚太内容分发大会暨CDN峰会

    6月29日,第十二届亚太内容分发大会暨CDN峰会在北京召开.大会聚集了行业领/袖.专家和学者,深度探讨CDN的技术发展.应用与未来发展趋势,会上还公布了2023边缘加速创新企业榜单,中国电信天翼云成功 ...

  10. Python无网络安装插件

    无网络安装插件 1.准备外网电脑,搭建所需python插件 2.将需要导出的插件,导出列表 pip freeze > .\req.txt 3.将插件导出到目录 pip download -r . ...