【go每日一题】 实现生产者消费者模式
基本描述
golang使用并发编程,实现一个生产者消费者模式,消费的任务耗时1-3秒,希望最终10秒内能够消费尽可能多的任务
代码
package test
import (
"fmt"
"math/rand"
"testing"
"time"
)
type ConsumeTask struct {
id int
execFunc func()
}
type Producer struct {
id int
ch chan *ConsumeTask
}
type Consumer struct {
id int
ch chan *ConsumeTask
}
func TestProducerConsumer(t *testing.T) {
taskCh := make(chan *ConsumeTask, 100)
defer close(taskCh)
producers := make([]*Producer, 0, 10)
consumers := make([]*Consumer, 0, 5)
// 创建十个消费者
for i := 0; i < 10; i++ {
consumers = append(consumers, NewConsumer(i, taskCh))
}
// 创建十个生产者
for i := 0; i < 10; i++ {
producers = append(producers, NewProducer(i, taskCh))
}
tasks := make(chan *ConsumeTask, 100)
for i := 0; i < 100; i++ {
t := &ConsumeTask{
id: i,
execFunc: func() {
dura := time.Duration(rand.Intn(3)+1) * time.Second
time.Sleep(dura)
fmt.Println("已经睡眠:", dura.String(), "s, 任务", i, "执行中...")
},
}
tasks <- t
}
defer close(tasks)
for _, producer := range producers {
// 闭包问题
//go func() {
// for t := range tasks {
// producer.Produce(t)
// }
//}()
go func(p *Producer) {
for t := range tasks {
p.Produce(t)
}
}(producer)
}
for _, consumer := range consumers {
闭包问题
//go func() {
// consumer.Consume()
//}()
go func(c *Consumer) {
c.Consume()
}(consumer)
}
time.Sleep(time.Second * 10)
}
func NewProducer(id int, ch chan *ConsumeTask) *Producer {
return &Producer{
id: id,
ch: ch,
}
}
func NewConsumer(id int, ch chan *ConsumeTask) *Consumer {
return &Consumer{
id: id,
ch: ch,
}
}
func (p *Producer) Produce(task *ConsumeTask) {
p.ch <- task
}
func (c *Consumer) Consume() {
for task := range c.ch {
fmt.Printf("消费者%d,正在消费\n", c.id)
task.execFunc()
}
}
结果分析
.....
已经睡眠: 1s s, 任务 26 执行中...
消费者6,正在消费
已经睡眠: 2s s, 任务 27 执行中...
消费者5,正在消费
已经睡眠: 1s s, 任务 30 执行中...
消费者3,正在消费
已经睡眠: 1s s, 任务 32 执行中...
消费者2,正在消费
已经睡眠: 3s s, 任务 22 执行中...
消费者8,正在消费
已经睡眠: 1s s, 任务 35 执行中...
消费者6,正在消费
已经睡眠: 1s s, 任务 37 执行中...
消费者3,正在消费
已经睡眠: 1s s, 任务 36 执行中...
消费者5,正在消费
已经睡眠: 2s s, 任务 29 执行中...
消费者4,正在消费
已经睡眠: 2s s, 任务 31 执行中...
消费者9,正在消费
已经睡眠: 1s s, 任务 39 执行中...
消费者8,正在消费
已经睡眠: 3s s, 任务 28 执行中...
消费者0,正在消费
已经睡眠: 2s s, 任务 38 执行中...
消费者2,正在消费
已经睡眠: 3s s, 任务 33 执行中...
消费者1,正在消费
已经睡眠: 3s s, 任务 34 执行中...
消费者7,正在消费
已经睡眠: 1s s, 任务 44 执行中...
消费者9,正在消费
已经睡眠: 1s s, 任务 41 执行中...
消费者3,正在消费
已经睡眠: 1s s, 任务 42 执行中...
消费者5,正在消费
已经睡眠: 1s s, 任务 45 执行中...
消费者8,正在消费
已经睡眠: 1s s, 任务 46 执行中...
消费者0,正在消费
--- PASS: TestProducerConsumer (10.00s)
PASS
可以看到,10s的时间内,每个任务耗时1-3s下,一共消费了46个任务,相比于顺序消费(3-10)个任务效率高了很多