如何正确限制 Goroutine 的数量

huangapple go评论107阅读模式
英文:

how to correctly limit number of goroutines

问题

我正在为您翻译以下内容:

我正在从标准输入中获取URL行,例如:
$ echo -e 'https://golang.org\nhttps://godoc.org\nhttps://golang.org' | go run 1.go .
任务是从每个网页中获取单词"Go"的数量。但是我不允许启动超过5个goroutine,并且只能使用标准库。
以下是我的代码:

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "bufio"
  6. "os"
  7. "regexp"
  8. "io/ioutil"
  9. "time"
  10. )
  11. func worker(id int, jobs<-chan string, results chan<-int) {
  12. t0 := time.Now()
  13. for url := range jobs {
  14. resp, err := http.Get(url)
  15. if err != nil {
  16. fmt.Println("打开URL时出现问题", url)
  17. results<-0
  18. //continue
  19. }
  20. defer resp.Body.Close()
  21. html, err := ioutil.ReadAll(resp.Body)
  22. if err != nil {
  23. continue
  24. }
  25. regExp:= regexp.MustCompile("Go")
  26. matches := regExp.FindAllStringIndex(string(html), -1)
  27. t1 := time.Now()
  28. fmt.Println("URL", url, "中的数量:", len(matches), "耗时:",
  29. t1.Sub(t0), "工作ID:", id)
  30. results<-len(matches)
  31. }
  32. }
  33. func main(){
  34. scanner := bufio.NewScanner(os.Stdin)
  35. jobs := make(chan string, 100)
  36. results := make(chan int, 100)
  37. t0 := time.Now()
  38. for w:= 0; w<5; w++{
  39. go worker(w, jobs, results)
  40. }
  41. var tasks int = 0
  42. res := 0
  43. for scanner.Scan() {
  44. jobs <- scanner.Text()
  45. tasks ++
  46. }
  47. close(jobs)
  48. for a := 1; a <= tasks; a++ {
  49. res += <-results
  50. }
  51. close(results)
  52. t2 := time.Now()
  53. fmt.Println("总计:",res, "总耗时:", t2.Sub(t0) );
  54. }

我认为它可以工作,直到我将超过5个URL(其中一个是不正确的)传递给标准输入。输出结果是:

  1. goroutine 9 [running]:
  2. panic ...

显然,额外的goroutine已经启动。如何修复它?也许有更方便的方法来限制goroutine的数量?

英文:

I'm getting in 'stdin' lines of URL's like:
$ echo -e 'https://golang.org\nhttps://godoc.org\nhttps://golang.org' | go run 1.go .
The task is to get from each WEB-page number of word "Go". But I'm not allowed to start more than 5 goroutines and can use only standard library
Here is my code:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;net/http&quot;
  5. &quot;bufio&quot;
  6. &quot;os&quot;
  7. &quot;regexp&quot;
  8. &quot;io/ioutil&quot;
  9. &quot;time&quot;
  10. )
  11. func worker(id int, jobs&lt;-chan string, results chan&lt;-int) {
  12. t0 := time.Now()
  13. for url := range jobs {
  14. resp, err := http.Get(url)
  15. if err != nil {
  16. fmt.Println(&quot;problem while opening url&quot;, url)
  17. results&lt;-0
  18. //continue
  19. }
  20. defer resp.Body.Close()
  21. html, err := ioutil.ReadAll(resp.Body)
  22. if err != nil {
  23. continue
  24. }
  25. regExp:= regexp.MustCompile(&quot;Go&quot;)
  26. matches := regExp.FindAllStringIndex(string(html), -1)
  27. t1 := time.Now()
  28. fmt.Println(&quot;Count for&quot;, url, &quot;:&quot;, len(matches), &quot;Elapsed time:&quot;,
  29. t1.Sub(t0), &quot;works id&quot;, id)
  30. results&lt;-len(matches)
  31. }
  32. }
  33. func main(){
  34. scanner := bufio.NewScanner(os.Stdin)
  35. jobs := make(chan string, 100)
  36. results := make(chan int, 100)
  37. t0 := time.Now()
  38. for w:= 0; w&lt;5; w++{
  39. go worker(w, jobs, results)
  40. }
  41. var tasks int = 0
  42. res := 0
  43. for scanner.Scan() {
  44. jobs &lt;- scanner.Text()
  45. tasks ++
  46. }
  47. close(jobs)
  48. for a := 1; a &lt;= tasks; a++ {
  49. res+=&lt;-results
  50. }
  51. close(results)
  52. t2 := time.Now()
  53. fmt.Println(&quot;Total:&quot;,res, &quot;Elapsed total time:&quot;, t2.Sub(t0) );
  54. }

I thought it works until I passed more than 5 URL (one of them was incorrect) to stdin. The output was:

  1. goroutine 9 [running]:
  2. panic ...

Obviously, extra goroutnes have been started. How to fix it? May be there are more convenient way to limit number of goroutines?

答案1

得分: 1

你的代码中只启动了5个goroutine。如果你真的想知道有多少个goroutine在运行,可以使用runtime.NumGoroutine函数。一些goroutine是由运行时启动的,还有一些是由网络获取数据时启动的。

英文:

> goroutine 9 [running]:

Some goroutines are started by the runtime, and by web fetches.

Looking at your code, you only started 5 goroutines.

If you really want to know how many go routines you are running use runtime.Numgoroutine

huangapple
  • 本文由 发表于 2017年4月27日 20:08:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/43657372.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定