一.GO并发编程综合应用
1.生产者消费者模式
1.1需求分析
生产者每秒生产一个商品,并通过物流公司取货
物流公司将商品运输到商铺
消费者阻塞等待商铺到货,需要消费10次商品
1.2实现原理
1.3代码实现:
package mainimport ("fmt""strconv""time"
)func main() {storageChan := make(chan Product, 10)shopChan := make(chan Product, 10)exitChan := make(chan bool, 1)for i := 1; i < 9; i++ {go Producer(storageChan, 10)}go Logistics(storageChan, shopChan)go Consumer(shopChan, 10, exitChan)if <-exitChan {return}
}// Product 商品
type Product struct {Name string
}// Producer 生产者
func Producer(storageChan chan<- Product, count int) {for {producer := Product{"商品:" + strconv.Itoa(count)}storageChan <- producercount--time.Sleep(time.Second)fmt.Println("生产了", producer)if count < 1 {return}}
}// Logistics 物流公司
func Logistics(storageChan <-chan Product, shopChan chan<- Product) {for {product := <-storageChanshopChan <- productfmt.Println("运输了", product)}
}// Consumer 消费者
func Consumer(shopChan <-chan Product, count int, exitChan chan<- bool) {for {product := <-shopChanfmt.Println("消费了", product)count--if count < 1 {exitChan <- truereturn}}
}
2.协程管道定时任务的应用
2.1需求分析
1.定时执行某个任务,类似延时消息队列
2.或者周期性的执行某个任务,类似定期同步某些数据
2.2实现原理
2.3代码实现:
package mainimport ("fmt""time"
)func main() {//方式1:fmt.Println("当前时间:", time.Now())//timer := time.NewTimer(time.Second * 3)//t := <-timer.C //timer.C一个只读的管道//fmt.Println(t)//方式二:t := <-time.After(time.Second * 3) //源码可见,实际上NewTimer(d).Cfmt.Println(t)
}
3.定时器的终止与重置
NewTimer, Stop, Reset
package mainimport ("fmt""math/rand""time"
)var flag bool = isStopTimer()func main() {//方式1:fmt.Println("当前时间:", time.Now())timer := time.NewTimer(time.Second * 3)if flag {timer.Stop() //如果停止了timer,还去拿fatal error: all goroutines are asleep - deadlock!} else {t := <-timer.C //timer.C一个只读的管道fmt.Println(t)}}func isStopTimer() bool {rand.Seed(time.Now().UnixNano())tempInt := rand.Intn(2) + 18if tempInt >= 18 {fmt.Println("已经找到了大于18,结束timer")return true} else {return false}
}func isResetTimer() int {rand.Seed(time.Now().UnixNano())tempInt := rand.Intn(4) + 19fmt.Println("已经找到",tempInt)return tempInt-18
}
4.需要每隔时间触发任务
4.1实现原理:
4.2代码实现
package mainimport ("fmt""time"
)func main() {var count int = 0ticker := time.NewTimer(time.Second * 1)go func() {for {t := <-ticker.Cfmt.Println("时间:", t.Format("2006-01-02 03:04:05PM"))count++if count > 2 {ticker.Stop()}}}()time.Sleep(time.Second * 10)fmt.Println("游戏结束")
}
4.3改造成任务队列
package mainimport ("fmt""sync""time"
)func main() {var count int = 0var wg sync.WaitGroupwg.Add(1)ticker := time.NewTicker(time.Second * 1)go func() {defer wg.Done()defer ticker.Stop()for {t := <-ticker.Cfmt.Println("时间:", t.Format("2006-01-02 03:04:05PM"))count++if count > 2 {return}}}()wg.Wait()fmt.Println("游戏结束")
}