如何优雅的控制goroutine的数量
1,为什么要控制goroutine的数量?
goroutine固然好,但是数量太多了,往往会带来很多麻烦,比如耗尽系统资源导致程序崩溃,或者CPU使用率过高导致系统忙不过来。比如:
for i:=; i < ; i++ {
go work()
}
2,用什么方法控制goroutine的数量?
要在每一次执行go之前判断goroutine的数量,如果数量超了,就要阻塞go的执行。第一时间想到的就是使用通道。每次执行的go之前向通道写入值,直到通道满的时候就阻塞了,如下:
var ch chan int
func work() {
//do something
<-ch
}
func main() {
ch = make(chan int, )
for i:=; i < ; i++ {
ch <-
go work()
}
}
这样每次同时运行的goroutine就被限制为10个了。但是新的问题出现了,因为并不是所有的goroutine都执行完了,在main函数退出之后,还有一些goroutine没有执行完就被强制结束了。这个时候我们就需要用到sync.WaitGroup。使用WaitGroup等待所有的goroutine退出。如下:
var wg *sync.WaitGroup
func work() {
defer wg.Done()
//do something
}
func main() {
wg = &sync.WaitGroup{}
for i:=; i < ; i++ {
wg.Add()
go work()
}
wg.Wait()//等待所有goroutine退出
}
3,优雅的使用并控制goroutine的数量
综上所述,我们封装一下,代码如下:
package gpool import (
"sync"
) type pool struct {
queue chan int
wg *sync.WaitGroup
} func New(size int) *pool {
if size <= {
size =
}
return &pool{
queue: make(chan int, size),
wg: &sync.WaitGroup{},
}
} func (p *pool) Add(delta int) {
for i := ; i < delta; i++ {
p.queue <-
}
for i := ; i > delta; i-- {
<-p.queue
}
p.wg.Add(delta)
} func (p *pool) Done() {
<-p.queue
p.wg.Done()
} func (p *pool) Wait() {
p.wg.Wait()
}
来段测试代码:
package gpool_test import (
"runtime"
"testing"
"time"
"gpool"
) func Test_Example(t *testing.T) {
pool := gpool.New()
println(runtime.NumGoroutine())
for i := ; i < ; i++ {
pool.Add()
go func() {
time.Sleep(time.Second)
println(runtime.NumGoroutine())
pool.Done()
}()
}
pool.Wait()
println(runtime.NumGoroutine())
}
good job,Over~
如何优雅的控制goroutine的数量的更多相关文章
- go中控制goroutine数量
控制goroutine数量 前言 控制goroutine的数量 通过channel+sync 使用semaphore 线程池 几个开源的线程池的设计 fasthttp中的协程池实现 Start Sto ...
- Java--Semaphore控制并发线程数量
package com; import java.util.concurrent.Semaphore; /** * Created by yangyu on 16/11/28. */ /** * Se ...
- Golang控制goroutine的启动与关闭
最近在用golang做项目的时候,使用到了goroutine.在golang中启动协程非常方便,只需要加一个go关键字: go myfunc(){ //do something }() 但是对于一些长 ...
- 深度分析如何在Hadoop中控制Map的数量
深度分析如何在Hadoop中控制Map的数量 guibin.beijing@gmail.com 很多文档中描述,Mapper的数量在默认情况下不可直接控制干预,因为Mapper的数量由输入的大小和个数 ...
- 一文带你更方便的控制 goroutine
上一篇我们讲了 go-zero 中的并发工具包 core/syncx. 从整体分析来看,并发组件主要通过 channel + mutex 控制程序中协程之间沟通. Do not communicate ...
- private关键字实现控制新建类数量
private关键字作为一个重要的关键字,我们在开发中会经常用到,可是你有没有想过通过private关键字我们可以创建一个别人无法通过new来新建的类呢?下面我们就来看一下: package retu ...
- mapreduce中控制mapper的数量
很多文档中描述,Mapper的数量在默认情况下不可直接控制干预,因为Mapper的数量由输入的大小和个数决定.在默认情况下,最终input占据了多少block,就应该启动多少个Mapper.如果输入的 ...
- 深度分析如何在Hadoop中控制Map的数量(摘抄)
很多文档中描述,Mapper的数量在默认情况下不可直接控制干预,因为Mapper的数量由输入的大小和个数决定.在默认情况下,最终input占据了多少block,就应该启动多少个Mapper.如果输入的 ...
- Smarty控制foreach输出数量
最近在搞ecshop,ecshop用的是smarty.在首页中想要修改展示的商品数量,但是用的是foreach,让我无从下手,在网上找了好久终于找到解决方案. <!--{foreach name ...
随机推荐
- Android 模仿微信发送图片 钟罩效果
参考资料http://trylovecatch.iteye.com/blog/1189452 http://bbs.51cto.com/thread-1031415-1.html### 1.添加资源文 ...
- QOpenGLFunctions的相关的使用(1)
QOpenGLFunctions的使用 1. QOpenGLFunctions 说明 QOpenGLFunctions 类提供了跨平台的OpenGl ES2.0 API版本. OpenGL 2. ...
- 28、vSocket模型详解及select应用详解
在上片文章已经讲过了TCP协议的基本结构和构成并举例,也粗略的讲过了SOCKET,但是讲解的并不完善,这里详细讲解下关于SOCKET的编程的I/O复用函数. 1.I/O复用:selec函数 在介绍so ...
- oc门
OC门电路,即集电极开路输出结构门电路,电路结构图为:
- UNIGUI集成HTML导航
UNIGUI集成HTML导航 先来一个效果图: ajaxRequest(MainForm.window,'openform',[]); procedure TMainForm.UniFormAjaxE ...
- Azure DevOps Server 2019 (TFS)安装教程
概述 Azure DevOps Server 2019 (之前的名称为TFS),作为微软Azure DevOps 的企业私有(on-premises)服务器,是一个为开发团队提供软件协作开发管理的服务 ...
- Postgres 的 Range 类型
mysql 不支持 Range 类型 零.介绍 1. 适用场景: a.可以用于实现 是否满足薪资需求 的功能 b.可以用于实现 是否符合上线时间 的功能 一.定义 1.类型范围 Postgres Se ...
- flask中邮件发送方法
from flask import Flask from flask_mail import Mail, Message app = Flask(__name__) #配置邮件:服务器/端口/传输层安 ...
- django安装与环境调配
91.查看当前已有虚拟环境 2.进入虚拟环境 3.退出当前虚拟环境 4.创建python隔离环境前先可用此先查看已经拥有什么版本的python 5.创建一个名为first的python隔离环境 6.安 ...
- vue10行代码实现上拉翻页加载更多数据,纯手写js实现下拉刷新上拉翻页不引用任何第三方插件
vue10行代码实现上拉翻页加载更多数据,纯手写js实现下拉刷新上拉翻页不引用任何第三方插件/库 一提到移动端的下拉刷新上拉翻页,你可能就会想到iScroll插件,没错iScroll是一个高性能,资源 ...