go牛刀小试之waitGroup等待协程完成(多组同步),速率控制

24 篇文章 1 订阅
7 篇文章 0 订阅

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值