使用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. Sealos Devbox 基础教程:使用 Cursor 从零开发一个 One API 替代品

    随着技术的成熟和 AI 的崛起,很多原本需要团队协作才能完成的工作现在都可以通过自动化和智能化的方式完成.于是乎,单个开发者的能力得到了极大的提升 - 借助各种工具,一个人就可以完成开发.测试.运维等 ...

  2. Qt编写地图综合应用28-闪烁点图

    一.前言 Qt除了内置了各种UI组件以外,还直接集成了浏览器控件,注意哦这可是跨平台的浏览器控件哦,在5.6版本以前集成的是webkit,以后集成的是webengine,使得程序的灵活性拓展性大大增强 ...

  3. 在Eclipse配置并编译worldwind java2.1.0源码,选中Src目录下gov.nasa.worldwindx.examples包下ApplicationTemplate.java类文件run时提示“javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V”异常的解决办法

    问题现象: 在Eclipse配置并编译worldwind java2.1.0源码,选中Src目录下gov.nasa.worldwindx.examples包下ApplicationTemplate.j ...

  4. HBase-1集群安装部署

    1.1 准备安装包 下载安装包并上传到hadoop01服务器 安装包下载地址:https://www.apache.org/dyn/closer.lua/hbase/2.2.6/hbase-2.2.6 ...

  5. weixueyuan-Nginx核心配置指令2

    https://www.weixueyuan.net/nginx/config/ Nginx配置文件详解 Nginx 默认编译安装后,配置文件都会保存在 /usr/local/nginx/conf 目 ...

  6. SpringCloud(2)---入门篇

    SpringCloud(6)---熔断降级理解.Hystrix实战 一.概念 1.为什么需要熔断降级 (1)需求背景 它是系统负载过高,突发流量或者网络等各种异常情况介绍,常用的解决方案. 在一个分布 ...

  7. 自定义swagger扩展解析jsondoc

    需求规定 为了减少注释和swagger注解的重复定义, 通过规范注释, 让swagger可以通过javadoc来产生 替换@Api.@ApiOperation.@ApiModel.@ApiModelP ...

  8. 关于hystrix.contrib.javanica.exception.FallbackDefinitionException: fallback method wasn't found异常

    在Spring中使用断路器后可能会遇到:com.netflix.hystrix.contrib.javanica.exception.FallbackDefinitionException: fall ...

  9. [业界方案] Yarn的业界解决方案和未来方向

    [业界方案] Yarn的业界解决方案和未来方向 目录 [业界方案] Yarn的业界解决方案和未来方向 0x00 摘要 0x01 Yarn 1.1 参考文章 0x02 分析 2.1 综述 2.1.1 y ...

  10. 我来告诉你怎么在macOS上畅玩金铲铲之战

    天选福星,灵蛇献瑞,<金铲铲之战>"天选福星"赛季好运上线!请接收这份来自<金铲铲之战>的新春邀约--"天选福星"正式回归,羁绊焕新升级 ...