实现广播机制
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逻辑")
}
}