关键,使用带缓冲的channel,当channel数量达到限制的最大数量时,会阻塞。
所有的goroutine必须都要运行,每次运行指定的数量(不可一次性运行,会导致带宽占满),这就要使用到waitgroup。
以下是没有使用waitgroup的情况,最后结果是并不是所有的url都打印了,这当然不是想要的结果。
package mainimport (
"fmt"
"sync"
"time"
)
var maxRoutineNum = 2
// routine限制最大数量
func main(){
ch := make(chan int, maxRoutineNum)
var urls = []string{
"http://www.golang.org/",
"http://www.google.com/",
"http://www.somestupidname.com/",
"http://www.golang.org/11",
"http://www.google.com/11",
"http://www.somestupidname.com/11",
"http://www.golang.org/22",
"http://www.google.com/22",
"http://www.somestupidname.com/22",
"http://www.golang.org/33",
"http://www.google.com/33",
"http://www.somestupidname.com/33",
} for _, u := range urls {
ch <- 1
go download1(u, ch)
}
}
// 模拟下载方法
func download1(url string, ch chan int) {
fmt.Println( url)
// 休眠2秒模拟下载
time.Sleep(time.Second * 2)
// 下载完成从ch取出数据
x:= <- ch
fmt.Println("x:",x)
}
下图为运行结果(每次运行的可能不一样,goroutine,你懂的),显然没有打印出所有的结果:
文章图片
再看使用了waitgroup的效果:
package mainimport (
"fmt"
"sync"
"time"
)
var maxRoutineNum = 2
// routine限制最大数量
func main(){
ch := make(chan int, maxRoutineNum)
var urls = []string{
"http://www.golang.org/",
"http://www.google.com/",
"http://www.somestupidname.com/",
"http://www.golang.org/11",
"http://www.google.com/11",
"http://www.somestupidname.com/11",
"http://www.golang.org/22",
"http://www.google.com/22",
"http://www.somestupidname.com/22",
"http://www.golang.org/33",
"http://www.google.com/33",
"http://www.somestupidname.com/33",
}
wg := sync.WaitGroup{}
for _, u := range urls {
wg.Add(1)
ch <- 1
go download(u, ch, &wg)
}
wg.Wait()
}
// 模拟下载方法
func download(url string, ch chan int , wg *sync.WaitGroup) {
fmt.Println( url)
// 休眠2秒模拟下载
time.Sleep(time.Second * 2)
// 下载完成从ch取出数据
x:= <- ch
wg.Done() fmt.Println("x:",x)
}
文章图片
【限制goroutine的数量】
推荐阅读
- Go|Docker后端部署详解(Go+Nginx)
- GO|GO,GO,GO!
- Go成长之路|go中判断空字符串、nil和len(t)的用法
- go编译tools
- go grpc安装与使用
- goroutine 调度原理
- Go|Go进阶之路——复杂类型
- Go进阶之路——变量
- Go进阶之路——流程控制语句