例如,这里有一个Go的函数,它会休眠一秒钟:
func doSomething(){
time.Sleep(time.Second)
}
当你想做某事时,你可以这样做:
func doManyThings(n int){
for range n{
do Something()
}
}
func main(){
doManyThings(10)
}
但是做这件事需要多长时间呢?比如说十次?
$ time go run main.go
real 0m10.256s
果然不出所料,大约10秒……如果我们想重复一百万次怎么办?那至少需要一百万秒,也就是将近十几天才行。
等等,这是怎么回事?计算机应该很快才对啊!
但是,我们可以通过编程让它们并发执行任务,而不是像上面那样顺序执行(一个接一个的),从而提高它们的速度。
如果你有多个 CPU(现在可以肯定都有),这些任务就会并行执行(这绝对是人类不应该尝试模拟的——想了解更多,你可以阅读约翰·哈里(Johann Hari )的《丢失焦点(Lost Focus)》一书)!
你可以通过以下这样生成新的goroutines,来同时运行 Go 中的许多事情:
func doManyThings(n int){
var wgsync.WaitGroup// create concurrency-safe counter
for range n{wg.Add(1)// increment counter by one
gofunc(){// launch function on new goroutine and continuedefer
wg.Done()// decrement counter on return from function
do Something()
}()
}wg.Wait()// wait till counter is 0 (all functions are done)}func main(){do ManyThings(1e6)}
那么,现在需要多长时间才能完成一百万次只执行一秒钟的事情呢?它在我的笔记本电脑上,不到三秒钟:
$ time go run main.go
real 0m2.667s
看到了没,这可比原来的十二天快多了!
// Now doSomething returns an error value. It's nil when all is good.
func doSomething()error{
time.Sleep(time.Second)
if rand.Intn(100)==0{// circa one percent of tasks will fail
return errors.New("we got a problem")
}
return nil
}
那么,我们如何获取在 goroutine 上并发执行的任务的输出呢?为此可以使用Channels:
func doManyThings(n int)[]error{
ch:=make(chanerror,n)// create channel of errors that can hold n items
for range n{ gofunc(){
ch<-doSomething()// send function's output to channel
}()}
var errs[]error
for range n{
err:=<-ch// receive value from channel and assign it to err
if err!=nil{
errs=append(errs,err)
}}return errs}
func main(){
n:=1_000_000
errs:=doManyThings(n)
fmt.Printf("Doing %d things there where %d errors.\n",n,len(errs))
}
如各位所见,我们不再需要counter计数器了。
这是因为我们再次循环(通过)来接收来自Channel的所有值。第二个循环实际上等待所有 Goroutine 完成——每个 Goroutine 只向通道发送一个值,因此通过从Channel读取值,我们能够知道所有Goroutine 都已完成了工作。
缓冲通道(具有一定容量)确保所有 Goroutine 都可以无阻塞地发送结果,即使我们尚未开始从Channel读取数据。
作者:洛逸
参考地址:
https://github.com/go-monk/doing-many-things-in-parallel
本篇文章为 @ 行动的大雄 创作并授权 21CTO 发布,未经许可,请勿转载。
内容授权事宜请您联系 webmaster@21cto.com或关注 21CTO 公众号。
该文观点仅代表作者本人,21CTO 平台仅提供信息存储空间服务。
请扫描二维码,使用微信支付哦。