关键,使用带缓冲的channel,当channel数量达到限制的最大数量时,会阻塞。
所有的goroutine必须都要运行,每次运行指定的数量(不可一次性运行,会导致带宽占满),这就要使用到waitgroup。
以下是没有使用waitgroup的情况,最后结果是并不是所有的url都打印了,这当然不是想要的结果。
package main
import (
"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 main
import (
"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)
}