WaitGroup 完成所有协程
/*
目标:利用sync包中的waitGroup对象来 等待各个协程gorutine完成;
方法:1) 定义变量sync.WatiGroup 2)传递给go routine,并每传递一次,waitgroup++, 3)go rutine内部设置延迟万层 defer wg.Done()函数
4)主线程中wg.Wait()
总结:设立外套Group 》给go routine刷计数器 》 内部设置延迟完成,返回才减数 》等待线程等;
典型的set-wait模式在一个组应用(关键是计数器 加减操作)
*/
package main
import (
"fmt"
"sync"
"time"
)
func workerRutine(id int, wg *sync.WaitGroup) {
defer wg.Done() //2 set wait: wait until this func finish
fmt.Println("Worker ID ", id, "Start work! ")
time.Sleep(time.Second)
fmt.Println("Worker ID", id, " completed!")
}
func main() {
var wg sync.WaitGroup //1 define sync.WG
for i:= 0; i < 5; i++ {
go workerRutine(i, &wg)
wg.Add(1) //3 counter works;
}
wg.Wait() //wait until counter minus to 0--ctrl main routine; a pair to defer wg.Done;
fmt.Println("All task finished!")
}
result
Worker ID 4 Start work!
Worker ID 1 Start work!
Worker ID 2 Start work!
Worker ID 3 Start work!
Worker ID 0 Start work!
Worker ID 1 completed!
Worker ID 4 completed!
Worker ID 0 completed!
Worker ID 3 completed!
Worker ID 2 completed!
All task finished!
rate control
/*
目标:通信机制协商阶段最重要的一项是,速率控制,确保接收端既不会饿死,也不会撑死;
方法:利用chan(size)做任务缓存、routine并发、打点器控制处理节奏;实现容易;
设想:两个场景,1个是固定的类似时钟一样,预估任务处理时间,一个节拍一个节拍完成;
2)复杂一点,除了正常的打点 外,允许一定突发量;在不超过缓存限制,很快完成突发任务;
涉及:time.Tick(time.Millis); time.Now();make(chan ,size), close(chan); 打点、报时、设立chan <- 入出、关闭chan(只能出 不再能入)
close(chan)设想一个高速公路,封路是封住入口,而非出口(你得让已经在这段路上的车开出来对吧,所以出口不会立刻封堵;可 <-a;不可b<-)
*/
package main
import (
"fmt"
"time"
)
func main () {
/* Case1: implement normal rate contrl: 5 size chan input, 200ms Tick ctrl, output "finish" */
request_in := make(chan int, 5)
rate_ctrlor := time.Tick(200 * time.Millisecond)
for i:= 1; i < 5; i++ {
request_in <- i
} //管道都是先存,后取;不存则取空
close(request_in) // cost all event; burn down
for i := range request_in {
<- rate_ctrlor //ctrl event purchase schedule
fmt.Println("处理事件 ", i, " ,时间 ", time.Now())
}
//time.Sleep(1 * time.Second)
/*Case2: normal ctrl as case 1 + burst event, burstSize=3*/
req2_in := make(chan int, 5)
rate_ctrlorC2 := time.Tick(200 * time.Millisecond)
burst_buff := make(chan time.Time, 3) //burst存time,让原本200ms的3个事件并发执行;routine大用了;
for j:= 1; j < 5; j ++ {
req2_in <- j
}
close(req2_in)
//burst buff need routine to "parallel" ctrl timeStep
go func() {
for t := range rate_ctrlorC2{
burst_buff <- t
}
}()
for i := 0; i < 3; i++ {
burst_buff <- time.Now() //immeditely finish 3 burst work
}
//simulate case2 task in server:
for k := 0; k <5; k ++ {
t := <- burst_buff
fmt.Println("带3个突发能力的事件处理:", k, ", 时间:", t)
}
}
result
处理事件 1 , 时间 2020-11-10 17:10:44.0011514 +0800 CST m=+0.203046001
处理事件 2 , 时间 2020-11-10 17:10:44.2086234 +0800 CST m=+0.410516501
处理事件 3 , 时间 2020-11-10 17:10:44.4053989 +0800 CST m=+0.607290501
处理事件 4 , 时间 2020-11-10 17:10:44.6028537 +0800 CST m=+0.804743901
带3个突发能力的事件处理: 0 , 时间: 2020-11-10 17:10:44.6028537 +0800 CST m=+0.804743901
带3个突发能力的事件处理: 1 , 时间: 2020-11-10 17:10:44.6028537 +0800 CST m=+0.804743901
带3个突发能力的事件处理: 2 , 时间: 2020-11-10 17:10:44.6028537 +0800 CST m=+0.804743901
带3个突发能力的事件处理: 3 , 时间: 2020-11-10 17:10:44.8151391 +0800 CST m=+1.017027801
带3个突发能力的事件处理: 4 , 时间: 2020-11-10 17:10:45.0120846 +0800 CST m=+1.213971901
Process finished with exit code 0