func main() {
jobs := []Job{job1, job2, job3}
numOfJobs := len(jobs)
resultsChan := make(chan *Result, numOfJobs)
jobChan := make(chan *job, numOfJobs)
go consume(numOfJobs, jobChan, resultsChan)
for i := 0; i < numOfJobs; i++ {
jobChan <- jobs[i]
}
close(jobChan)
for i := 0; i < numOfJobs; i++ {
<-resultsChan
}
close(resultsChan)
}
func (b *Blockchain) consume(num int, jobChan chan *Job, resultsChan chan *Result) {
for i := 0; i < num; i++ {
go func() {
job := <-jobChan
resultsChan <- doJob(job)
}()
}
}
在上面的示例中,作业被推入jobChan,goroutines将其从jobChan中拉出并同时执行作业并将结果推送到resultsChan。然后我们将结果从resultsChan中拉出来。
问题1:
在我的代码中,没有序列化/线性化结果。虽然工作按job1,job2,job3的顺序排列。结果可能是job3,job1,job2,取决于哪一个花费的时间最长。
我仍然希望同时执行这些作业,但是,我需要确保结果来自结果可能与作为作业进入的顺序相同。
问题2:
我有大约300k个工作,这意味着代码将生成多达300k goroutines。拥有如此多的goroutine是否有效,或者我最好将这些工作分成100个左右,并让每个goroutine通过100而不是1。
答案 0 :(得分:1)
这是我处理序列化(以及设置有限数量的工作人员)的方法。我设置了一些带有输入和输出字段和同步通道的工作对象,然后我循环遍历它们,完成他们已经完成的任何工作并给他们一份新工作。然后我最后通过他们来接收剩下的任何已完成的工作。请注意,您可能希望工作人员数量稍微超过核心数,这样即使有一个异常长的工作,您也可以保持所有资源的忙碌。代码位于http://play.golang.org/p/PM9y4ieMxw及以下。
这是毛茸茸的(在我坐下来写一个例子之前比我记得更毛茸茸!) - 很想看到其他人有什么,或者只是更好的实施或完全不同的方式来实现你的目标。
package main
import (
"fmt"
"math/rand"
"runtime"
"time"
)
type Worker struct {
in int
out int
inited bool
jobReady chan bool
done chan bool
}
func (w *Worker) work() {
time.Sleep(time.Duration(rand.Float32() * float32(time.Second)))
w.out = w.in + 1000
}
func (w *Worker) listen() {
for <-w.jobReady {
w.work()
w.done <- true
}
}
func doSerialJobs(in chan int, out chan int) {
concurrency := 23
workers := make([]Worker, concurrency)
i := 0
// feed in and get out items
for workItem := range in {
w := &workers[i%
concurrency]
if w.inited {
<-w.done
out <- w.out
} else {
w.jobReady = make(chan bool)
w.done = make(chan bool)
w.inited = true
go w.listen()
}
w.in = workItem
w.jobReady <- true
i++
}
// get out any job results left over after we ran out of input
for n := 0; n < concurrency; n++ {
w := &workers[i%concurrency]
if w.inited {
<-w.done
out <- w.out
}
close(w.jobReady)
i++
}
close(out)
}
func main() {
runtime.GOMAXPROCS(10)
in, out := make(chan int), make(chan int)
allFinished := make(chan bool)
go doSerialJobs(in, out)
go func() {
for result := range out {
fmt.Println(result)
}
allFinished <- true
}()
for i := 0; i < 100; i++ {
in <- i
}
close(in)
<-allFinished
}
请注意,此示例中只有in
和out
包含实际数据 - 所有其他频道仅用于同步。