package main
import (
"fmt"
"time"
)
type Demo struct {
input chan string
output chan string
goroutine_cnt chan int
}
func NewDemo() *Demo {
d := new(Demo)
d.input = make(chan string, 8192)
d.output = make(chan string, 8192)
d.goroutine_cnt = make(chan int, 10)
return d
}
func (this *Demo) Goroutine() {
this.input <- time.Now().Format("2006-01-02 15:04:05")
time.Sleep(time.Millisecond * 500)
<-this.goroutine_cnt
}
func (this *Demo) Handle() {
for t := range this.input {
fmt.Println("datatime is :", t, "goroutine count is :", len(this.goroutine_cnt))
this.output <- t + "handle"
}
}
func main() {
demo := NewDemo()
go demo.Handle()
for i := 0; i < 10000; i++ {
demo.goroutine_cnt <- 1
go demo.Goroutine()
}
close(demo.input)
}
如上边示例,Goroutine()函数,每隔500毫秒写入一个时间戳到管道中,不考虑管道的读取时间,也就是说,每个Goroutine会存在大概500毫秒时间,如果不做控制的话,一瞬间可以开启上万个甚至更多的goroutine出来,这样系统就会奔溃。
在上述代码中,我们引入了带10个buffer的chan int字段,每创建一个goroutine时,就会向这个chan中写入一个1,每完成一个goroutine时,就会从chan中弹出一个1。当chan中装满10个1时,就会自动阻塞,等待goroutine执行完,弹出chan中的值时,才能继续开启goroutine。通过chan阻塞特点,实现了goroutine的最大并发量控制。