H5W3
当前位置:H5W3 > go > 正文

【go】这段协程怎么不阻塞?

程序片段如下:

runtime.GOMAXPROCS(runtime.NumCPU())
//maxPage := getMaxPage()
maxPage := 10
if maxPage > 0 {
jobs := make(chan int, maxPage)
results := make(chan []map[string]string, maxPage)
// 招聘工人,让他们工作(待命),每个工人会从jobs管道里获得任务,工人干活,把结果放到results管道
for w := 1; w <= runtime.NumCPU(); w++ {
go worker(w, jobs, results)
}
db, err := mysqlUtil.CreateReadDb()
if err != nil {
log.Fatal("connect db err ", err)
fmt.Println("connect db err ", err)
}
//分配任务
for j := 1; j <= maxPage; j++ {
jobs <- j
}
close(jobs)
for data := range results {
//写数据库操作
}
close(results)
fmt.Println("all done...")
}

woker函数如下:

func worker(id int, jobs <-chan int, results chan<- []map[string]string) {
for j := range jobs {
url := host + "/type/1/" + strconv.Itoa(j) + ".html"
fmt.Println()
data := getData(url)
fmt.Printf("worker %d finished job %d", id, j)
fmt.Println()
results <- data
}
}

现在的问题是程序在

for data := range results {
//写数据库操作
}

这一个地方阻塞住了,job都完成了,job完成后的数据都放到了result里面,上面也都完成了写库操作,为啥阻塞在了那里,不往下执行了呢?

range results 这个操作只有在关闭管道之后,才会继续往下执行。否则会一直阻塞。

            for j := 1; j <= maxPage; j++ {
data := <- results
//写数据库
fmt.Println(len(data))
}
close(results)

程序有点问题,处理结果这样操作就行了,就不会阻塞了。

go func(){
for data := range results {
//写数据库操作
}
}()
把这个放goruntine即可。另外还要注意控制主进程退出的时机,防止goruntine没处理完主进程就退出。
阻塞的原因是results在缓存为空的时候会阻塞除非results被close,你这里主进程被阻塞了,一直跑不到close的地方。

回答

本文地址:H5W3 » 【go】这段协程怎么不阻塞?

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址