关于利用go实现异步读写的写法分享
同步写法
t := time.Now()
fmt.Println("hello")
skip := 3000
for i := 1; i <= 51178; i += skip {
fmt.Println(i)
db.Model(DB.DBUserLog{}).Where("ul_id > ? ", i).Limit(skip).Find(&entityList)
var buf bytes.Buffer
for _, entity := range entityList {
m := make(map[string]interface{})
j, _ := json.Marshal(entity)
_ = json.Unmarshal(j, &m)
buf.Write(j)
buf.WriteString("\n")
}
// 模拟写耗时操作
time.Sleep(1 * time.Second)
}
elapsed := time.Since(t)
fmt.Println("app run time", elapsed)
异步写法
t = time.Now()
go func() {
skip := 3000
for i := 1; i <= 51178; i += skip {
fmt.Println(i)
db.Model(DB.DBUserLog{}).Where("ul_id > ? ", i).Limit(skip).Find(&entityList)
read <- entityList
}
readEnd <- 1
}()
write := func() {
for {
select {
case data := <-read:
var buf bytes.Buffer
for _, entity := range data {
m := make(map[string]interface{})
j, _ := json.Marshal(entity)
_ = json.Unmarshal(j, &m)
buf.Write(j)
buf.WriteString("\n")
}
// 模拟写耗时操作
time.Sleep(time.Second)
_ = util.FilePutContents("ceshi.txt", buf.Bytes(), true)
break
case <-readEnd:
return
}
}
}
write()
elapsed = time.Since(t)
fmt.Println("app run time", elapsed)
速度上当读操作和写操作的执行逻辑较为接近的时候效果较为明显。这种写法可以把一次读写看为一次操作,一次读写的用时变为了 min (readTime,writeTIme)。 而非 readTime + writeTime 。如果进行一些数据导出处理事,如果时间较长,且读写操作时间较为接近事可以尝试将读写异步话。这样除了中间 channel 中是阻塞的, 各自的读写操作逻辑是异步的。可以一定程度上提整体运行速度。如果读写操作用时相差较大,则优化效果就不那么明显了。
本作品采用《CC 协议》,转载必须注明作者和本文链接
既然是一个程序里的,那用 mutex 会不会更好呢?