Goroutine常见并发模式
- 生产者 - 消费者模式:
- 模式描述:生产者负责生成数据,消费者负责处理数据。两者通过通道(channel)进行数据传递。这种模式解耦了数据的生产和消费过程,提高了程序的并发处理能力。
- 示例代码:
package main
import (
"fmt"
)
func producer(out chan<- int) {
for i := 0; i < 10; i++ {
out <- i
}
close(out)
}
func consumer(in <-chan int) {
for num := range in {
fmt.Println("Consumed:", num)
}
}
func main() {
ch := make(chan int)
go producer(ch)
consumer(ch)
}
- 扇入(Fan - In)模式:
- 模式描述:多个输入通道的数据被合并到一个输出通道。通常用于多个生产者的数据汇总。
- 示例代码:
package main
import (
"fmt"
)
func producer1(out chan<- int) {
for i := 0; i < 5; i++ {
out <- i * 2
}
close(out)
}
func producer2(out chan<- int) {
for i := 0; i < 5; i++ {
out <- i * 3
}
close(out)
}
func fanIn(in1, in2 <-chan int, out chan<- int) {
go func() {
for num := range in1 {
out <- num
}
}()
go func() {
for num := range in2 {
out <- num
}
}()
go func() {
// 等待两个输入通道关闭
<-in1
<-in2
close(out)
}()
}
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
out := make(chan int)
go producer1(ch1)
go producer2(ch2)
go fanIn(ch1, ch2, out)
for num := range out {
fmt.Println("Fan - In:", num)
}
}
- 扇出(Fan - Out)模式:
- 模式描述:一个输入通道的数据被分发到多个输出通道,通常用于将任务分发给多个消费者并行处理。
- 示例代码:
package main
import (
"fmt"
)
func fanOut(in <-chan int, out1, out2 chan<- int) {
for num := range in {
select {
case out1 <- num:
case out2 <- num:
}
}
close(out1)
close(out2)
}
func consumer1(in <-chan int) {
for num := range in {
fmt.Println("Consumer1:", num)
}
}
func consumer2(in <-chan int) {
for num := range in {
fmt.Println("Consumer2:", num)
}
}
func main() {
in := make(chan int)
out1 := make(chan int)
out2 := make(chan int)
go func() {
for i := 0; i < 10; i++ {
in <- i
}
close(in)
}()
go fanOut(in, out1, out2)
go consumer1(out1)
go consumer2(out2)
select {}
}
生产者 - 消费者模式适用场景
- 任务队列处理:例如在一个Web应用中,有大量的任务需要处理,如图片处理、视频转码等。可以将这些任务作为数据由生产者放入任务队列(通道),消费者从队列中取出任务并处理。这样可以避免任务堆积在单个处理单元,提高整体处理效率。
- 数据采集与分析:在大数据采集场景中,数据采集模块作为生产者,不断地从各种数据源采集数据并放入通道。数据分析模块作为消费者,从通道中获取数据进行分析处理。这种模式可以保证数据采集和分析的解耦,即使数据采集速度和分析速度不匹配,也能通过通道缓冲进行协调。