go routine + channel 实践
做个实验,造一个长度一个亿的slice struct
对其内部作出修改,分别使用并发和不用并发,看看时间上会差多少。
不使用协程版本:
type Data struct {
   Id int
   Info string
}
func main(){
   //channel := make(chan[]Data,10)
   var data []Data
   for i:= 0;i<1e8;i++{
      data = append(data,Data{Id: i,Info: "a"})
   }
   startTime := time.Now().UnixNano()
   for i := 0;i<len(data);i++{
      data[i].Info+="b"
   }
   //var wg sync.WaitGroup
   //for i := 0;i<10;i++{
   // wg.Add(1)
   // go process(data[i*1e7:(i+1)*1e7],channel,&wg)
   //}
   //wg.Wait()
   //data = data[:0]
   //for i := 0;i <10;i++ {
   // var tmp []Data
   // tmp = <-channel
   // data = append(data, tmp...)
   //}
   //close(channel)
   
   endTime:= time.Now().UnixNano()
   tag:=0
   for _,v:= range data{
      if v.Info!="ab"{tag++}
   }
   fmt.Printf("tag: %d\nlength: %d\n",tag,len(data))
   fmt.Printf("running time: %d ms",(endTime-startTime)/1e6)
}
func process(ar []Data,channel chan []Data,wg *sync.WaitGroup){
   defer wg.Done()
   for i := 0;i<len(ar);i++{
      ar[i].Info+="b"
   }
   channel <- ar
}
输出:
tag: 0
length: 100000000
running time: 3080 ms
解释:tag用来验证是否所有Data都被修改,length用来验证最后有没有拿到完整的一个亿的slice struct
tag =0 length=1e8说明咱代码结果是正确的。
使用协程版本:
package main
import (
"fmt"
"sync"
"time"
)
type Data struct {
Id int
Info string
}
func main(){
channel := make(chan[]Data,10)
var data []Data
for i:= 0;i<1e8;i++{
data = append(data,Data{Id: i,Info: "a"})
}
startTime := time.Now().UnixNano()
//for i := 0;i<len(data);i++{
// data[i].Info+="b"
//}
var wg sync.WaitGroup
for i := 0;i<10;i++{
wg.Add(1)
go process(data[i*1e7:(i+1)*1e7],channel,&wg)
}
wg.Wait()
data = data[:0]
for i := 0;i <10;i++ {
var tmp []Data
tmp = <-channel
data = append(data, tmp...)
}
close(channel)
endTime:= time.Now().UnixNano()
tag:=0
for _,v:= range data{
if v.Info!="ab"{tag++}
}
fmt.Printf("tag: %d\nlength: %d\n",tag,len(data))
fmt.Printf("running time: %d ms",(endTime-startTime)/1e6)
}
func process(ar []Data,channel chan []Data,wg *sync.WaitGroup){
defer wg.Done()
for i := 0;i<len(ar);i++{
ar[i].Info+="b"
}
channel <- ar
}
输出:
tag: 0
length: 100000000
running time: 896 ms
解释:tag和length依然正确,不再赘述。
开了十个routinue,时间上大概快了三到四倍,看到米有,这就是go routinue+channel的效果~~~~~~~
菜菜的我再多说几句番外~~~~~~~~~~~:
1.如果没有给channel缓冲区的话,就会死锁,原因嘛,老八股文了,无缓冲区的channel写入以后不消费掉的话写入是阻塞的。所以加个缓冲区就好了。
2.如果不使用sync 的withGroup,就会奇妙的发现tag不等于0,也就意味着有一堆Data没有修改成功,原因嘛,老八股文了,routine没有执行完嘛。。。。
withGroup add done wait配合操作,让他执行完再消费就好了。

                
            
        
浙公网安备 33010602011771号