假设我有以下代码读取行数,每行乘以2,并逐行打印每一行。
我想使用N名工人。每个工人每次需要M行并处理它们。更重要的是,我希望输出以与输入相同的顺序打印。但此处的示例并不保证输出的打印顺序与输入的顺序相同。
https://gobyexample.com/worker-pools
以下网址还显示了一些示例。但我认为它们不符合我的要求。问题是输入可以任意长。在打印之前无法将所有内容保存在内存中。必须有一种方法可以从工人那里获得一些输出,可以确定工人的输出是否已准备好打印,然后打印。听起来应该有一个高手goroutine这样做。但我不确定如何最有效地实现它,因为当N很大时,这个主要的gorountine很容易成为瓶颈。
How to collect values from N goroutines executed in a specific order?
是否有人能够按顺序显示工人产生的示例程序,并在打印结果后立即打印结果?
$ cat main.go
#!/usr/bin/env gorun
// vim: set noexpandtab tabstop=2:
package main
import (
"bufio"
"fmt"
"strconv"
"io"
"os"
"log"
)
func main() {
stdin := bufio.NewReader(os.Stdin)
for {
line, err := stdin.ReadString('\n')
if err == io.EOF {
if len(line) != 0 {
i, _ := strconv.Atoi(line)
fmt.Println(i*2)
}
break
} else if err != nil {
log.Fatal(err)
}
i, _ := strconv.Atoi(line[:(len(line)-1)])
fmt.Println(i*2)
}
}
答案 0 :(得分:-1)
如果工人知道他们的初始订单,例如例如,通知行号,然后让工人保留该信息(只是行号)。然后,您的员工将该信息反馈给您的结果渠道。您的结果汇总了从结果渠道接收的代码,然后在进一步处理(例如打印)之前根据初始订购信息对结果进行排序。
以下是您展示的其中一个示例的快速修改。
包主要
import "fmt"
import "time"
type Result struct {
Data, Seq int
}
type Job struct {
Data string
Seq int
}
func worker(id int, jobs <-chan Job, results chan<- Result) {
for j := range jobs {
fmt.Println("worker", id, "started job", j)
time.Sleep(time.Second)
fmt.Println("worker", id, "finished job", j)
results <- Result{len(j.Data), j.Seq}
}
}
func main() {
workload := 5
jobs := make(chan Job, 100)
results := make(chan Result, 100)
output := make([]Result, workload)
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
for j := 0; j < workload; j++ {
jobs <- Job{ // explicit to make it clear
Data: fmt.Sprintf("blah blah blah %d", j),
Seq: j,
}
}
close(jobs)
// receive results
for a := 1; a <= workload; a++ {
res := <-results
output[res.Seq] = res
// uncomment to see unordered
// fmt.Printf("received: %#v", res)
}
for _, out := range output {
fmt.Printf("output %#v\n", out)
}
}
顺便说一句:如果您事先不知道自己的工作量,这种方法效果不佳......在这种情况下,接收结果的代码在处理已经收到并订购的部分(家庭作业)时需要更加智能一些:) 。基本上等待第0行然后等待下一行或打印已按顺序接收的内容。
玩得开心!