Goroutine被for循环阻塞了吗? [英] Goroutines blocked by for loop?
问题描述
我有以下代码实现了工作队列:
I have the following code which implements a worker queue:
package main
import (
"fmt"
"net/http"
"io"
"time"
)
var (
linkQueue chan Link
scraperQueue chan chan Link
)
func CycleDirectory(page int) {
linkQueue <- Link{Name: "asd"}
}
type Link struct {
Name string
}
func (s Scraper) Start() {
fmt.Println("Started")
go func() {
for {
s.ScraperQueue <- s.Link
select {
case link := <-s.Link:
fmt.Println(fmt.Sprintf("%v", s.Id) + ": Received " + link.Name)
case <-s.QuitChan:
fmt.Println("Closed")
return
}
}
}()
}
func (s Scraper) Stop() {
go func() {
s.QuitChan <- true
}()
}
type Scraper struct {
Id int
Link chan Link
ScraperQueue chan chan Link
QuitChan chan bool
}
func InitScraper(id int, scraperQueue chan chan Link) Scraper {
return Scraper {
Id: id,
Link: make(chan Link),
ScraperQueue: scraperQueue,
QuitChan: make(chan bool),
}
}
func HelloServer(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "hello, world!\n")
}
func main() {
linkQueue = make(chan Link, 2000)
numScrapers := 2
scraperQueue = make(chan chan Link, numScrapers)
for i := 0; i < numScrapers; i++ {
s := InitScraper(i+1, scraperQueue)
s.Start()
}
go func() {
for {
select {
case link := <-linkQueue:
go func() {
scraper := <-scraperQueue
scraper <- link
}()
}
}
}()
CycleDirectory(1)
// time.Sleep(1 * time.Millisecond)
for {
// select {
// }
}
// http.HandleFunc("/hello", HelloServer)
// http.ListenAndServe(":12345", nil)
}
使用包含if语句(或内部没有内容)的for循环运行此代码,刮板不会打印收到的消息。使用net / http中的ListenAndServe函数进行阻止,它将打印收到的消息。使用睡眠阻止1毫秒,我收到了消息。然后将一条select语句放入for循环中,我也收到消息。
Running this code using a for loop containing an if statement (or nothing inside), the scraper does not print a received message. Blocking using the ListenAndServe function from net/http, it prints the received message. Blocking using sleep for 1 ms, I receive the message. And putting a select statement in the for loop, I also receive the message.
为什么没有选择语句的for循环不允许执行在工作人员队列,以及如何处理此问题。我需要在for循环中使用if语句来检查所有工作是否已经完成,以便退出循环并结束程序。
Why is the for loop without a select statement not allowing for execution of the message sending in the worker queues, and how would I go about handling this. I need an if statement in the for loop to check if all the work has been done so I can exit the loop and end the program.
更新
Amd的建议可以解决此问题。这是我使用sync.WaitGroup
包main
Amd's suggestion is a solution to this problem. Here is my updated code using sync.WaitGroup package main
import (
"fmt"
"sync"
)
var (
linkQueue chan Link
scraperQueue chan chan Link
wg sync.WaitGroup
)
func CycleDirectory(page int) {
wg.Add(1)
linkQueue <- Link{Name: "asd"}
}
type Link struct {
Name string
}
func (s Scraper) Start() {
fmt.Println("Started")
go func() {
for {
s.ScraperQueue <- s.Link
select {
case link := <-s.Link:
Scrape(s.Id, link.Name)
s.Stop()
case <-s.QuitChan:
fmt.Println("Closed")
wg.Done()
return
}
}
}()
}
func (s Scraper) Stop() {
go func() {
s.QuitChan <- true
}()
}
type Scraper struct {
Id int
Link chan Link
ScraperQueue chan chan Link
QuitChan chan bool
}
func Scrape(id int, name string) {
fmt.Println(fmt.Sprintf("%v", id) + ": Received " + name)
}
func InitScraper(id int, scraperQueue chan chan Link) Scraper {
return Scraper {
Id: id,
Link: make(chan Link),
ScraperQueue: scraperQueue,
QuitChan: make(chan bool),
}
}
func main() {
linkQueue = make(chan Link, 2000)
numScrapers := 2
scraperQueue = make(chan chan Link, numScrapers)
for i := 0; i < numScrapers; i++ {
s := InitScraper(i+1, scraperQueue)
s.Start()
}
go func() {
for {
select {
case link := <-linkQueue:
go func() {
scraper := <-scraperQueue
scraper <- link
}()
}
}
}()
CycleDirectory(1)
wg.Wait()
fmt.Println("Done")
}
推荐答案
您可以使用 sync.WaitGroup
停止程序退出,直到完成所有工作。
在围棋场:
You may use sync.WaitGroup
to stop the program from exiting until all the work is done.
Try it on The Go Playground:
package main
import (
"fmt"
"sync"
"time"
)
var (
wg sync.WaitGroup
)
func main() {
wg.Add(1)
go func() {
defer wg.Done()
time.Sleep(2 * time.Second)
}()
fmt.Println("Wait...")
wg.Wait()
fmt.Println("Done.")
}
这篇关于Goroutine被for循环阻塞了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!