Generator
Go-并发模式2(Patterns)https://blog.csdn.net/lady_killer9/article/details/120145534
https://blog.csdn.net/lady_killer9/article/details/120145534
一句话总结:返回channel,不断从channel接收
扇入模式
Go-并发模式2(Patterns)https://blog.csdn.net/lady_killer9/article/details/120145534
https://blog.csdn.net/lady_killer9/article/details/120145534
一句话总结:接收多个channel,并入一个channel并返回
超时模式
总体超时
Go-并发模式2(Patterns)https://blog.csdn.net/lady_killer9/article/details/120145534
https://blog.csdn.net/lady_killer9/article/details/120145534
一句话总结:循环前定时,结合select
单次超时
Go-并发模式2(Patterns)https://blog.csdn.net/lady_killer9/article/details/120145534
https://blog.csdn.net/lady_killer9/article/details/120145534
一句话总结:循环内定时,结合select
周期定时
Go-并发编程基础(goroutine、channel、select等)https://blog.csdn.net/lady_killer9/article/details/116144462
https://blog.csdn.net/lady_killer9/article/details/116144462
time与select一节
一句话总结:循环前定时,结合select
callback模式
go开启一个协程,并不知道什么时候会结束,其他语言一般会有callback,在go中,函数可以作为参数实现callback,这里再说一种channel实现callback的思路。
开启的协程,可以在结束后像一个channel中写入值,main routine中读取,即可实现阻塞直到完成。
package main import ( "fmt" "math/rand" "time" ) func doSomething(event string,ch chan<-bool) { time.Sleep(time.Duration(rand.Intn(500))*time.Millisecond) ch<-true } func main() { ch := make(chan bool) go doSomething("event",ch) for{ select { case <-ch: fmt.Println("finish...") return } } }
一般是等待第一个协程结束或所有协程结束,如果多个协程的话可以计数。
sync里面有WaitGroup,也可以实现,等到sync的时候再说。
缓存模式
在Go-并发模式1(Basic Examples)中提到了channel有buffer,但是Rob Pike在2012年的演讲中没有讲。
举个例子,假设厨师做饭一会儿做的快,可能是凉菜,一会儿做的慢,可能是佛跳墙。服务员的端菜速度是一定的,如果菜没有地方放,只能等待服务员拿的话,就会很慢,因为厨师做快了没有地方放(阻塞),做慢了的话服务员要一直等(阻塞)。
package main import ( "fmt" "math/rand" "time" ) var food = make(chan string) func cook(foods []string){ for _,f := range foods{ if f == "凉菜"{ time.Sleep(100*time.Millisecond) food<-"凉菜" }else { time.Sleep(800*time.Millisecond) food<-"佛跳墙" } } } func server(finish chan bool){ for { select { case name:=<-food: time.Sleep(time.Duration(rand.Intn(600))*time.Millisecond) fmt.Println("客官,上菜了:",name) finish<-true default: //fmt.Println("服务员在等待...") } } } func main() { foods := []string{"凉菜","凉菜","凉菜","凉菜","凉菜","凉菜","佛跳墙","凉菜"} n := len(foods) cnt := 0 finish := make(chan bool) start := time.Now() go cook(foods) go server(finish) for{ select { case <-finish:{ cnt += 1 if cnt == n{ fmt.Println(time.Since(start)) return } } } } }
上面代码是没有缓存的,会慢一些,如果把food改为
var food = make(chan string,6)
就会快一些,结果如下:
总结
添加goroutine进行并发后,程序发生了以下变化:
- 慢速->快速
- 顺序->并发
- 不健壮->健壮
参考
更多Go相关内容:Go-Golang学习总结笔记
有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。