golang 并发
并发模式实例
例子
消息生成器
模拟消息生成接收
package main
import (
"fmt"
"math/rand"
"time"
)
// 模拟两秒内产生数据
func msgGen(name string) chan string {
c := make(chan string)
go func() {
i := 0
for {
time.Sleep(time.Duration(rand.Intn(2000)) * time.Millisecond)
c <- fmt.Sprintf("service %s: message %d", name, i)
i++
}
}()
return c
}
// 同时等待多个服务
/*
拿一个管道汇总多个管道的数据
*/
func fanIn(chs ...chan string) chan string {
c := make(chan string)
for _, ch := range chs {
go func(in chan string) {
for {
c <- <-in
}
}(ch)
}
return c
}
/*
select 版
*/
func fanInBySelect(c1, c2 chan string) chan string {
c := make(chan string)
go func() {
for {
select {
case m := <-c1:
c <- m
case m := <-c2:
c <- m
}
}
}()
return c
}
func main() {
m1 := msgGen("service1")
m2 := msgGen("service2")
m3 := msgGen("service3")
m := fanIn(m1, m2, m3)
for {
fmt.Println(<-m)
}
}
并发任务控制实例
通过上面的程序,模拟非阻塞、超时等、任务中断,优雅退出例子
package main
import (
"fmt"
"math/rand"
"time"
)
func msgGen(name string, done chan struct{}) chan string {
c := make(chan string)
go func() {
i := 0
for {
// 如果要中止任务,需要跳出来
select {
case <-time.After(time.Duration(rand.Intn(2000)) * time.Millisecond):
c <- fmt.Sprintf("service %s: message %d", name, i)
case <-done:
fmt.Println("cleaning up")
time.Sleep(time.Second * 2) // 模拟两秒才清理完
fmt.Println("cleaning done")
done <- struct{}{}
return
}
i++
}
}()
return c
}
// 同时等待多个服务
/*
拿一个管道汇总多个管道的数据
*/
func fanIn(chs ...chan string) chan string {
c := make(chan string)
for _, ch := range chs {
go func(in chan string) {
for {
c <- <-in
}
}(ch)
}
return c
}
/*
select 版
*/
func fanInBySelect(c1, c2 chan string) chan string {
c := make(chan string)
go func() {
for {
select {
case m := <-c1:
c <- m
case m := <-c2:
c <- m
}
}
}()
return c
}
// 任务控制
// 非阻塞等待
func nonBlockingWait (c chan string) (string, bool) {
select {
case m := <- c:
return m, true
default:
return "", false
}
}
func timeoutWait(c chan string, timeout time.Duration) (string, bool) {
select {
case m := <- c:
return m, true
case <-time.After(timeout):
return "", false
}
}
func main() {
done := make(chan struct{})
m1 := msgGen("service1", done)
m2 := msgGen("service2", done)
m3 := msgGen("service3", done)
m := fanIn(m1, m2, m3)
for i := 0; i < 5; i++{
fmt.Println(<-m)
if m , ok := timeoutWait(m2, time.Second); ok {
fmt.Println(m)
} else {
fmt.Println("no message from svc2")
}
}
done <- struct{}{}
time.Sleep(time.Second)
// 模拟服务器优雅推出
<- done
fmt.Println("server exit")
}