Golang非阻塞缓冲区

时间:2016-06-09 20:06:53

标签: go concurrency nonblocking

同步示例:

type job struct {
    Id int
    Message string
}

for {
    // getJob() blocks until job is received
    job := getJob()
    doSomethingWithJob(job)
}

我希望处理来自getJob doSomethingWithJob的工作。例如getJob可以是从MessagingQueue接收的有效负载,例如RabbitMQ / Beanstalkd或处理HTTP请求。

我不想阻止getJob,而我doSomethingWithJob&反之亦然。但是我想控制/缓冲作业的数量,这样我就不会使系统过载。例如最大并发度为5.

go例程的概念目前让我很困惑,所以任何正确方向的指针都会非常感激,以帮助我学习。

更新:感谢@JimB的帮助。为什么工人5总是接受这份工作?

jobCh := make(chan *job)

// Max 5 Workers
for i := 0; i < 5; i++ {

    go func() {

        for job := range jobCh {
            time.Sleep(time.Second * time.Duration(rand.Intn(3)))
            log.Println(i, string(job.Message))
        }
    }()
}

for {
    job, err := getJob()
    if err != nil {
        log.Println("Closing Channel")
        close(jobCh)
        break
    }

    jobCh <- job
}

log.Println("Complete")

示例输出

2016/06/09 22:19:57 5 {"id":10692,"name":"Test Message"}
2016/06/09 22:19:57 5 {"id":10687,"name":"Test Message"}
2016/06/09 22:19:57 5 {"id":10699,"name":"Test Message"}
2016/06/09 22:19:57 5 {"id":10701,"name":"Test Message"}
2016/06/09 22:19:57 5 {"id":10703,"name":"Test Message"}
2016/06/09 22:19:57 5 {"id":10704,"name":"Test Message"}

1 个答案:

答案 0 :(得分:4)

您可以从频道开始播放5个goroutines来呼叫doSomethingWithJob。这样,同时处理的作业永远不会超过5个。

jobCh := make(chan *job)

// start 5 workers to process jobs
for i := 0; i < 5; i++ {
    go func() {
        for job := range jobCh {
            doSomethingWithJob(job)
        }
    }()
}

// send jobs to workers as fast as we can
for {
    jobCh <- getJob()
}