两个generator,1个worker消耗,如果worker处理慢(worker处理sleep 5s)。则会出现有些n没有打印。
package main
import (
"fmt"
"time"
"math/rand"
)
func generator() chan int {
out := make(chan int)
go func() {
i := 0
for {
time.Sleep(
time.Duration(rand.Intn(1500)) *
time.Millisecond)
out <- i
i++
}
}()
return out
}
func worker(id int, c chan int) {
for n := range c {
time.Sleep(5 * time.Second)
fmt.Printf("Worker %d received %d\n",
id, n)
}
}
// <- chan
// chan <-
func createWorker(id int) chan <- int {
c := make(chan int)
go worker(id, c)
return c
}
func main() {
//var c1, c2 chan int // c1 and c2 = nil
var c1, c2 = generator(), generator()
worker := createWorker(0)
n := 0
hasValue := false
for {
var activeWorker chan<- int
if hasValue {
activeWorker = worker
}
select {
case n = <-c1:
//fmt.Println("Received from c1:", n)
hasValue = true
case n = <-c2:
//fmt.Println("Received from c2", n)
hasValue = true
case activeWorker <- n:
hasValue = false
}
}
}
代码:https://github.com/NIGHTFIGHTING/go_learning/blob/master/src/channel/select/select.go
package main
import (
"fmt"
"time"
"math/rand"
)
func generator() chan int {
out := make(chan int)
go func() {
i := 0
for {
time.Sleep(
time.Duration(rand.Intn(1500)) *
time.Millisecond)
out <- i
i++
}
}()
return out
}
func worker(id int, c chan int) {
for n := range c {
// 模拟worker处理慢情况
//time.Sleep(5 * time.Second)
time.Sleep(1 * time.Second)
fmt.Printf("Worker %d received %d\n",
id, n)
}
}
// <- chan
// chan <-
func createWorker(id int) chan <- int {
c := make(chan int)
go worker(id, c)
return c
}
func main() {
//var c1, c2 chan int // c1 and c2 = nil
var c1, c2 = generator(), generator()
worker := createWorker(0)
var values []int
tm := time.After(10 * time.Second)
tick := time.Tick(time.Second)
for {
var activeWorker chan<- int // activeWorker is nil,下面activeWorker <- activeValue会阻塞
var activeValue int
if len(values) > 0 {
activeWorker = worker
activeValue = values[0]
}
select {
case n := <-c1:
// 缓存数据
values = append(values, n)
case n := <-c2:
// 缓存数据
values = append(values, n)
case activeWorker <- activeValue:
// 数据为准备号activeWorker是nil channel,这里会不会执行
values = values[1:]
case <- time.After(800 * time.Millisecond):
// 没有tick情况下表示,800ms内generator没有生成数据
// 有tick表示,两次select处理时差是否超过800ms
fmt.Println("timeout")
case <- tick:
fmt.Println("queue len = ", len(values))
case <- tm:
// 这段程序运行10s退出
fmt.Println("bye")
return
}
}
}