设计思路
- 任务队列:使用Go语言的
channel
作为共享的任务队列,用于各个goroutine
获取任务。
- 停止信号:定义一个全局的
stop
channel,当特定任务完成时,向这个channel
发送信号,通知其他goroutine
停止。
- 标签与跳转:这里的“标签与跳转”类似一种协调机制,在Go语言中可以通过
select
语句结合stop
channel来实现类似功能。select
语句会阻塞直到其某个case
分支可以继续执行,这样就可以实现类似跳转等待特定信号的效果。
具体实现
package main
import (
"fmt"
"sync"
)
type Task struct {
ID int
// 其他任务相关字段
}
func worker(taskQueue <-chan Task, stop <-chan struct{}, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case task, ok := <-taskQueue:
if!ok {
return
}
if task.ID == 100 {
// 处理特定任务
fmt.Println("处理特定任务ID为100")
close(stop) // 通知其他goroutine停止
} else {
// 处理其他任务
fmt.Println("处理任务ID:", task.ID)
}
case <-stop:
return
}
}
}
func main() {
var wg sync.WaitGroup
taskQueue := make(chan Task)
stop := make(chan struct{})
// 启动多个goroutine
numWorkers := 3
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go worker(taskQueue, stop, &wg)
}
// 模拟添加任务
tasks := []Task{
{ID: 1},
{ID: 100},
{ID: 2},
}
for _, task := range tasks {
taskQueue <- task
}
close(taskQueue)
wg.Wait()
fmt.Println("所有goroutine已停止")
}
标签与跳转的作用
- 标签作用:在这个程序中,特定任务ID(100)就相当于一个“标签”,通过判断任务的ID来识别特定任务。
- 跳转作用:
select
语句中的case <-stop:
分支就相当于“跳转”,一旦stop
channel接收到信号,goroutine
就会从处理任务的流程跳转到退出流程,从而优雅停止当前任务处理并退出。这种机制使得goroutine
之间可以有效地进行通信和协调,实现并发程序的有序停止。