程序片段如下:
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】这段协程怎么不阻塞?