如何从工人那里订购结果,好像没有使用工人一样?

时间:2018-02-06 03:35:43

标签: go worker

假设我有以下代码读取行数,每行乘以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)
    }
}

1 个答案:

答案 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行然后等待下一行或打印已按顺序接收的内容。

玩得开心!