如何正确限制 Goroutine 的数量

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

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,并且只能使用标准库。
以下是我的代码:

package main

import (
  "fmt"
  "net/http"
  "bufio"
  "os"
  "regexp"
  "io/ioutil"
  "time"
)

func worker(id int, jobs<-chan string, results chan<-int) {
  t0 := time.Now()
  for url := range jobs {
    resp, err := http.Get(url)
    if err != nil {
      fmt.Println("打开URL时出现问题", url)
      results<-0
      //continue
    }
    defer resp.Body.Close()
    html, err := ioutil.ReadAll(resp.Body)
    if err != nil {
      continue
    }
    regExp:= regexp.MustCompile("Go")
    matches := regExp.FindAllStringIndex(string(html), -1)
    t1 := time.Now()
    fmt.Println("URL", url, "中的数量:", len(matches), "耗时:", 
t1.Sub(t0),  "工作ID:", id)
    results<-len(matches)
  }
}

func main(){
  scanner := bufio.NewScanner(os.Stdin)
  jobs := make(chan string, 100)
  results := make(chan int, 100)
  t0 := time.Now()
  for w:= 0; w<5; w++{
    go worker(w, jobs, results)
  }
  var tasks int = 0
  res := 0
  for scanner.Scan() {
      jobs <- scanner.Text()
      tasks ++
  }
  close(jobs)
  for a := 1; a <= tasks; a++ {
    res += <-results
  }
  close(results)
  t2 := time.Now()
  fmt.Println("总计:",res, "总耗时:", t2.Sub(t0) );
}

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

 goroutine 9 [running]:
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:

    package main
import (
&quot;fmt&quot;
&quot;net/http&quot;
&quot;bufio&quot;
&quot;os&quot;
&quot;regexp&quot;
&quot;io/ioutil&quot;
&quot;time&quot;
)
func worker(id int, jobs&lt;-chan string, results chan&lt;-int) {
t0 := time.Now()
for url := range jobs {
resp, err := http.Get(url)
if err != nil {
fmt.Println(&quot;problem while opening url&quot;, url)
results&lt;-0
//continue
}
defer resp.Body.Close()
html, err := ioutil.ReadAll(resp.Body)
if err != nil {
continue
}
regExp:= regexp.MustCompile(&quot;Go&quot;)
matches := regExp.FindAllStringIndex(string(html), -1)
t1 := time.Now()
fmt.Println(&quot;Count for&quot;, url, &quot;:&quot;, len(matches), &quot;Elapsed time:&quot;, 
t1.Sub(t0),  &quot;works id&quot;, id)
results&lt;-len(matches)
}
}
func main(){
scanner := bufio.NewScanner(os.Stdin)
jobs := make(chan string, 100)
results := make(chan int, 100)
t0 := time.Now()
for w:= 0; w&lt;5; w++{
go worker(w, jobs, results)
}
var tasks int = 0
res := 0
for scanner.Scan() {
jobs &lt;- scanner.Text()
tasks ++
}
close(jobs)
for a := 1; a &lt;= tasks; a++ {
res+=&lt;-results
}
close(results)
t2 := time.Now()
fmt.Println(&quot;Total:&quot;,res, &quot;Elapsed total time:&quot;, t2.Sub(t0) );
}

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

 goroutine 9 [running]:
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:

确定