如何优雅的控制goroutine的数量
2016-05-27 15:44
471 查看
1,为什么要控制goroutine的数量?
goroutine固然好,但是数量太多了,往往会带来很多麻烦,比如耗尽系统资源导致程序崩溃,或者CPU使用率过高导致系统忙不过来。比如:
2,用什么方法控制goroutine的数量?
要在每一次执行go之前判断goroutine的数量,如果数量超了,就要阻塞go的执行。第一时间想到的就是使用通道。每次执行的go之前向通道写入值,直到通道满的时候就阻塞了,如下:
这样每次同时运行的goroutine就被限制为10个了。但是新的问题出现了,因为并不是所有的goroutine都执行完了,在main函数退出之后,还有一些goroutine没有执行完就被强制结束了。这个时候我们就需要用到sync.WaitGroup。使用WaitGroup等待所有的goroutine退出。如下:
3,优雅的使用并控制goroutine的数量
综上所述,我们封装一下,代码如下:
来段测试代码:
good job,Over~
goroutine固然好,但是数量太多了,往往会带来很多麻烦,比如耗尽系统资源导致程序崩溃,或者CPU使用率过高导致系统忙不过来。比如:
for i:=0; i < 10000; i++ { go work() }
2,用什么方法控制goroutine的数量?
要在每一次执行go之前判断goroutine的数量,如果数量超了,就要阻塞go的执行。第一时间想到的就是使用通道。每次执行的go之前向通道写入值,直到通道满的时候就阻塞了,如下:
var ch chan int func work() { //do something <-ch } func main() { ch = make(chan int, 10) for i:=0; i < 10000; i++ { ch <- 1 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:=0; i < 10000; i++ { wg.Add(1) 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 <= 0 { size = 1 } return &pool{ queue: make(chan int, size), wg: &sync.WaitGroup{}, } } func (p *pool) Add(delta int) { for i := 0; i < delta; i++ { p.queue <- 1 } for i := 0; 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(100) println(runtime.NumGoroutine()) for i := 0; i < 1000; i++ { pool.Add(1) go func() { time.Sleep(time.Second) println(runtime.NumGoroutine()) pool.Done() }() } pool.Wait() println(runtime.NumGoroutine()) }
good job,Over~
相关文章推荐
- Oracle阻塞(blockingblocked)实例详解
- 科学知识:同步、异步、阻塞和非阻塞区别
- SQL2008中SQL应用之-阻塞(Blocking)应用分析
- Oracle 阻塞(blocking blocked)介绍和实例演示
- 利用sys.sysprocesses检查SqlServer的阻塞和死锁
- c# 方法可变数量的参数
- node.js回调函数之阻塞调用与非阻塞调用
- JavaScript获取页面中表单(form)数量的方法
- php定义参数数量可变的函数用法实例
- Jquery ajax 同步阻塞引起的UI线程阻塞问题
- js异步加载的三种解决方案
- SQL Server误区30日谈 第2天 DBCC CHECKDB会导致阻塞
- Oracle RAC环境下的阻塞(blocking blocked)介绍和实例演示
- Java基于Runtime调用外部程序出现阻塞的解决方法
- nodejs中实现阻塞实例
- PHP递归遍历指定目录的文件并统计文件数量的方法
- jQuery检测输入的字符串包含的中英文的数量
- PHP session文件独占锁引起阻塞问题解决方法
- JavaScript实现仿淘宝商品购买数量的增减效果
- java执行bat命令碰到的阻塞问题的解决方法