Golang中的channel详解(三):channel具体使用场景

实现广播机制

package main

import (
	"fmt"
	"sync"
)

type signal struct{}

func spawnGroup(count int, groupSignal chan struct{}) <-chan signal {
	c := make(chan signal) //用于让main goroutine阻塞的channel

	var wg sync.WaitGroup
	wg.Add(count)

	//创建goroutine
	for i := 1; i <= count; i++ {
		go func(index int) {
			<-groupSignal //等待main goroutine通知执行

			//处理业务逻辑
			//...

			fmt.Println(index, "子goroutine任务执行完成")

			wg.Done()
		}(i)
	}

	go func() {
		// 等待所有子goroutine执行完成
		wg.Wait()
		c <- signal{} // 通知main goroutine
	}()

	return c
}

func main() {

	groupSignal := make(chan struct{})
	c := spawnGroup(5, groupSignal)

	//执行业务逻辑
	//...

	fmt.Println("给子goroutine发送执行信号")
	// main goroutine任务执行完成,通知执行相关逻辑
	close(groupSignal) //通知刚创建的所有 routine

	<-c // 等待子goroutine执行完成

	fmt.Println("所有任务都执行完成")
}

执行结果如下(每次执行,每个子goroutine的执行顺序可能会有所不同):

给子goroutine发送执行信号
1 子goroutine任务执行完成
3 子goroutine任务执行完成
2 子goroutine任务执行完成
5 子goroutine任务执行完成
4 子goroutine任务执行完成
所有任务都执行完成

控制任务并行数量

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	var active = make(chan struct{}, 3) //最大并行任务数量,最多 3 个
	var wg sync.WaitGroup

	for j := 1; j < 10; j++ {
		wg.Add(1)
		//执行任务
		go func(i int) {
			//通知任务开始执行,当数量达到最大时阻塞
			active <- struct{}{}
			fmt.Printf("当前任务: %d, 正在执行的任务数量: %d \n", i, len(active))
			time.Sleep(2 * time.Second)
			//任务执行完成,通知结束
			<-active
			wg.Done()
		}(j)
	}
	wg.Wait()
}

超时控制

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan struct{})

	//执行任务
	go runJob(ch)

	select {
	case <-ch:
		fmt.Println("任务完成!")
	case <-time.After(2 * time.Second): //2秒超时
		fmt.Println("超时!")
	}
}

func runJob(c chan<- struct{}) {
	//执行业务逻辑
	//...
	time.Sleep(3 * time.Second) // 模拟处理业务话费时间,给3秒,会输出超时,改为1秒,就会输出任务完成
	//执行完成后给信号
	c <- struct{}{}
}

实现心跳机制

package main

import (
	"log"
	"time"
)

func main() {
	ch := make(chan struct{})

	//执行任务
	go runJob(ch)

	select {}
}

func runJob(c chan struct{}) {
	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()
	for {
		select {
		case <-c:
			//处理业务逻辑
		case <-ticker.C:
			log.Println("心跳一次")
		}
	}
}

使用select的default分支灵活处理

package main

import (
	"log"
	"time"
)

func main() {
	ch := make(chan struct{})

	//执行任务
	go runJob(ch)

	time.Sleep(1 * time.Second)
}

func runJob(c chan struct{}) {
	select {
	case <-c:
		//处理对应逻辑
	default:
		//处理德福特逻辑
		log.Println("执行default逻辑")
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路多辛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值