go生产者消费者模型

913 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述

使用goroutine和channel实现生产者消费者模型。

二、思路分析

  1. 开启两个channel,一个作为任务队列,一个阻塞主线程,等待协程任务完成。
  2. 两种go协程,一个协程作为生产者向任务队列中送入任务数据,多个消费者协程从任务队列中获取任务,执行任务,完成任务后向done channel中送入数据,表示任务完成。
  3. 生产者协程向通道中送入生成任务,结束时关闭通道。
  4. 消费者协程开启for循环不断获取通道中的任务,如果通道中为空,则break循环,从循环中退出,并且向done通道中写入数据,表示该协程任务已完成
  5. 主线程开启一个生产者协程和多个消费者协程,并且从done通道中获取数据,如果数据为准备就绪,主协程阻塞,等待消费者协程完成任务。

三、AC 代码

package main

import "fmt"

func Producer(ch chan int) {
	defer close(ch)
	for i := 0; i < 10; i++ {
		ch <- i
	}
}
func Consumer(id int, ch chan int, done chan bool) {
	for {
		value, ok := <-ch
		if ok {
			fmt.Printf("id %d,value %d \n", id, value)
		} else {
			break
		}
	}
	done <- true
}

func main() {
	ch := make(chan int, 3)
	conum := 2
	done := make(chan bool, conum)
	for i := 0; i < conum; i++ {
		go Consumer(i, ch, done)
	}
	go Producer(ch)
	for i := 0; i < conum; i++ {
		<-done
	}
}

使用waitgroup

func producer(ch chan int) {
	defer close(ch)
	for i := 0; i < 10; i++ {
		ch <- i
	}
}
func waitconsumer(id int, ch chan int, wg *sync.WaitGroup) {
	for {
		if value, ok := <-ch; ok {
			fmt.Printf("ID:%d,task:%d\n", id, value)
		} else {
			break
		}
	}
	wg.Done()
}
func main() {
	var wg sync.WaitGroup
	ch := make(chan int, 3)
	go producer(ch)
	conum := 2
	wg.Add(conum)
	for i := 0; i < conum; i++ {
		go waitconsumer(i, ch, &wg)
	}
	wg.Wait()
}

四、总结

生产者消费者模型,需要考虑阻塞主协程可以使用sync.waitgroup等待任务完成,也可以开启一个等待任务完成的通道,阻塞主线程。