在这个例子中,我们将创建一个 "缓冲 "通道,其容量最多为11个资源槽。如果超过11个作业,它会拒绝它们。我们将只有一个工作者/goroutine在运行,以便处理作业。应用程序将阻塞,直到所有工作完成,所以没有工作丢失。
改进措施
虽然这是一个 "基本 "的例子,但必须考虑一些额外的功能,例如:
-
终止长期运行的作业。
-
运行多个工作者。
-
防止通道接受更多的作业,同时优雅地停止工作者。
-
杀死所有工作者。
例子
这里也有一个很好的例子:
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var (
// wg is used to force the application wait for all goroutines to finish before exiting.
wg sync.WaitGroup
// jobChan is a buffered channel that has the capacity of maximum 11 resource slot.
jobChan = make(chan int, 11)
// waiters is used to make goroutines sleep in order to simulate time it took to process the job.
waiters = []int{0, 1, 2, 3, 4}
)
func main() {
rand.Seed(time.Now().UnixNano())
fmt.Println("BEGIN")
// Tell how many worker you will be running.
wg.Add(1)
// Run 1 worker to handle jobs.
go worker(jobChan, &wg)
// Send 10 jobs to job channel.
for i := 1; i <= 10; i++ {
if !queueJob(i, jobChan) {
fmt.Println("Channel is full... Service unavailable...")
}
}
// Close the job channel.
close(jobChan)
// Block exiting until all the goroutines are finished.
wg.Wait()
fmt.Println("END")
}
// queueJob puts job into channel. If channel buffer is full, return false.
func queueJob(job int, jobChan chan<- int) bool {
select {
case jobChan <- job:
return true
default:
return false
}
}
// worker processes jobs.
func worker(jobChan <-chan int, wg *sync.WaitGroup) {
// As soon as the current goroutine finishes (job done!), notify back WaitGroup.
defer wg.Done()
fmt.Println("Worker is waiting for jobs")
for job := range jobChan {
fmt.Println("Worker picked job", job)
wait := time.Duration(rand.Intn(len(waiters)))
time.Sleep(wait * time.Second)
// Process the job ...
fmt.Println("Worker completed job", job, "in", int(wait), "second(s)")
}
}
测试
BEGIN
Worker is waiting for jobs
Worker picked job 1
Worker completed job 1 in 4 second(s)
Worker picked job 2
Worker completed job 2 in 1 second(s)
Worker picked job 3
Worker completed job 3 in 4 second(s)
Worker picked job 4
Worker completed job 4 in 3 second(s)
Worker picked job 5
Worker completed job 5 in 2 second(s)
Worker picked job 6
Worker completed job 6 in 1 second(s)
Worker picked job 7
Worker completed job 7 in 1 second(s)
Worker picked job 8
Worker completed job 8 in 2 second(s)
Worker picked job 9
Worker completed job 9 in 1 second(s)
Worker picked job 10
Worker completed job 10 in 2 second(s)
END
如果作业量超过通道的限制,你会看到一些作业被拒绝。例如,如果你发送15个作业到限制为11个作业的通道,你应该看到类似下面的情况,有4个作业被拒绝:
BEGIN
Channel is full... Service unavailable...
Channel is full... Service unavailable...
Channel is full... Service unavailable...
Channel is full... Service unavailable...
...
...