go 通道的运用(控制并发的数量)

无缓冲通道:同步通道

//对无缓冲channel类型的发送与接收操作,一定要放在两个不同的Goroutine中进行,否则会导致deadlock。
//无缓冲通道,必须接收和发送都准备好了才能执行。否则会阻塞。
//所以无缓冲通道相当于是同步通道了。
var helloChan = make(chan struct{})

func Test33() {
	fmt.Println("数一下羊吧~~~")
	go SaySheep()
	<-helloChan //这里会暂时阻塞直到SaySheep遍历执行输出10只羊后收到helloChan通道发送的值才会继续下一步
	fmt.Println("you are bad bad")
}

func SaySheep() {
	for i := 0; i < 10; i++ {
		fmt.Println("🐏")
	}
	helloChan <- struct{}{} //空结构体不占用内存
}

输出结果:
在这里插入图片描述

有缓冲通道:控制协程、并发的数量

//利用有缓冲通道控制协程的数量,利用waitGroup控制协程的结束
var wg sync.WaitGroup

func Test35() {
	//利用有缓冲通道控制协程数量为3
	ch := make(chan struct{}, 3)
	for i := 0; i < 20; i++ {
		wg.Add(1)
		//这里缓冲通道写满了3个数据后,就会阻塞,等待Weekend方法中发送通道里的数据,才能继续执行
		ch <- struct{}{}
		go Weekend(ch, i)
	}
	wg.Wait()
}

func Weekend(ch chan struct{}, i int) {
	fmt.Println("周末拉", i)
	fmt.Println(" goroutine count = ", runtime.NumGoroutine())
	// time.Sleep(time.Duration(i) * time.Second)
	<-ch
	wg.Done()
}

输出结果:
在这里插入图片描述

无缓冲通道也可以控制并发的数量

//无缓冲通道控制协程数量
//思想:开启固定的goroutine池,然后设置无缓冲的通道作为接收任务的中介,固定的协程读取到通道中任务就执行任务。
var wg sync.WaitGroup

func Test36() {
	var cowChan = make(chan string)
	var go_num = 3 //指定协程的数量为3
	for i := 0; i < go_num; i++ {
		go CallCowBoy(cowChan)
	}
	for i := 0; i < 20; i++ {
		SendTask(cowChan, i)
		//也可以直接写在这里
		// wg.Add(1)
		// cowChan <- "🐂🤠" + strconv.Itoa(i)
	}
	wg.Wait()
}

func CallCowBoy(ch chan string) {
	for v := range ch {
		fmt.Printf("%s are very busy \n", v)
		fmt.Println(" goroutine count = ", runtime.NumGoroutine())
		wg.Done()
	}
}

func SendTask(ch chan string, i int) {
	wg.Add(1)
	ch <- "🐂🤠" + strconv.Itoa(i)
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值