我有以下代码实现了工作队列:
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循环中,我也收到消息。
为什么没有select语句的for循环不允许执行在工作队列中发送的消息,以及我将如何处理这一问题。我需要在for循环中使用if语句来检查是否所有工作都已完成,因此我可以退出循环并结束程序。
更新资料
Amd的建议是解决此问题的方法。这是我使用sync.WaitGroup包主要的更新代码
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
用来停止程序退出,直到完成所有工作。
在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.")
}
我有一个带感应帽的覆盆子皮。我制作了一个二进制时钟,我想在Sense hat的显示器上显示并保持更新。然而,我想要的能力,开关时钟与操纵杆中间。一切都很好,除了我的时钟的更新循环阻止任何新的输入一旦启动。 我一直在考虑如何解决这个问题。如何允许脚本/时钟保持运行,并且仍然接受来自操纵杆的新操作。但是一旦while循环开始,我就卡住了。我不知道该用谷歌搜索什么。我已经开始研究async/await,
问题内容: 正如我从golang文档中了解到的,如果我使用8个内核的cpu(intel i7)设置runtime.GOMAXPROCS(8),然后启动无限循环goroutine,则不应阻塞其他gorutine,因为有足够的线程和goprocs。但是,当使用net / http包时,情况并非如此,无限循环goroutine会在几次调用后阻塞http服务器。谁能帮助解释原因? 如果我注释“无限循环”这
线程实例的join()方法可用于将一个线程的执行开始“连接”到另一个线程的执行结束,这样一个线程在另一个线程结束之前不会开始运行。如果对线程实例调用join(),则当前运行的线程将阻塞,直到线程实例完成执行 但是如果我有多个线程并且当我在循环内部调用join时。所有线程并行运行。但是根据连接的概念,首先连接的线程应该完成,然后只有主线程才允许连接其他线程。 } 在上面的代码中,如果第一个线程被连接
我们已经知道 Vert.x Api 是非阻塞,并且不会堵塞事件循环。 如果你堵塞事件循环,那事件循环将不能做别的事,因为它被阻塞了。如果所有的event loop被阻塞了,应用程序将完全停止! 所以不要这样做!你已经被警告。 阻塞的例子包括: Thread.sleep() 等待锁 等待互斥体或监视器 (例如同步段) 做一个长时间的数据库操作和等待返回 做复杂的计算,需要很长的时间。 死循环。 如果
我试图在for循环中获得for循环,因此输出如下: 我希望输出显示一个正方形 我不知道它为什么不这样做。下面是我的代码: