package main
import (
"fmt"
"sync"
)
// 定义任务结构体
type Task struct {
ID int
}
func producer(id int, tasks chan<- Task, wg *sync.WaitGroup) {
defer wg.Done()
for i := 0; i < 5; i++ {
task := Task{ID: id*10 + i}
tasks <- task
fmt.Printf("Producer %d sent task %d\n", id, task.ID)
}
}
func consumer(id int, tasks <-chan Task, wg *sync.WaitGroup) {
defer wg.Done()
for task := range tasks {
fmt.Printf("Consumer %d received task %d\n", id, task.ID)
}
}
func main() {
const numProducers = 3
const numConsumers = 2
tasks := make(chan Task)
var wg sync.WaitGroup
// 启动生产者
for i := 0; i < numProducers; i++ {
wg.Add(1)
go producer(i, tasks, &wg)
}
// 启动消费者
for i := 0; i < numConsumers; i++ {
wg.Add(1)
go consumer(i, tasks, &wg)
}
// 等待所有生产者完成任务
go func() {
wg.Wait()
close(tasks)
}()
// 等待所有消费者完成任务
wg.Wait()
}
确保程序正确性和高效性的措施:
- 使用通道进行通信:通过Go语言的通道(channel)来传递任务,这是Go语言中实现并发安全通信的机制,避免了数据竞争。
- 同步等待组:使用
sync.WaitGroup
来等待所有生产者和消费者完成任务。在启动每个生产者和消费者协程时调用wg.Add(1)
,在协程结束时调用wg.Done()
,并在主函数中调用wg.Wait()
来等待所有协程完成。
- 正确关闭通道:在所有生产者完成任务后,通过
close(tasks)
关闭通道,这样消费者协程在读取完通道中的所有数据后会退出循环,避免死锁。
- 合理分配任务:通过多个生产者和消费者并行工作,提高任务处理的效率。生产者快速地将任务发送到通道,消费者从通道中取出任务并处理,实现了生产者和消费者之间的解耦,提高了程序的整体效率。