Go 并发实战核心编程【一】

简介: Go 并发实战核心编程【一】

Go 并发实战核心编程【一】



1. 需求


  • 启动一个goroutine,将1-10000的数字放入chan中
  • 启动4个goroutine从chan中读取数字,并计算是不是素数
  • 是素数就讲结果放入结果chan中
  • 最后遍历结果chan,打印素数集合


2. 思路


这道题思路很简单,首先明确一个点就是这个需求有三种类型的goroutine:

  • 第一种类型就是生产者,它主要负责数据的生产;
  • 第二种类型就是消费者,他主要负责消费数据做加工;
  • 第三种类型就是main goroutine,他主要负责调度这些goroutine并且等待他们退出。


明确思路之后我们在深入分析下,这个需求需要三个chan:

  • 第一个就是生产者和消费者之间的通信是需要一个chan的,这个chan就是生产者生产数字放到chan中,消费者从chan取出数字。
  • 第二个就是消费者计算完素数之后结果得放入一个chan中,这个chan需要和main goroutine通信,因为main goroutine需要遍历打印这些素数;
  • 最后一个就是main goroutine需要等待所有消费goroutine的退出,因为我不知道消费者什么时候结束,所以也需要一个chan和main goroutine通信。


因此这个需求需要三种类型的goroutine和三种类型的chan。


3. 编码


package main
import "fmt"
// 生产者
func producer(intChan chan int) {
 fmt.Println("producer goroutine 开始生产数据啦")
 for i:=1; i<10000; i++ {
  intChan <- i
 }
 //生产完毕就关闭
 close(intChan)
 fmt.Println("producer goroutine 退出啦")
}
// 消费者
func consumer(intChan chan int, primeChan chan int, exitChan chan bool) {
 fmt.Println("consumer goroutine 开始消费数据啦")
 for {
  num, ok := <- intChan
  if !ok {
   break //生产者已经关闭intChan 那么消费者读取到关闭信号之后就应该退出
  }
  //计算素数
  flag := true
  for i:=2; i<num; i++ {
   if num%i == 0 {
    flag = !flag
    break
   }
  }
  //素数存储到primeChan中
  if flag {
   primeChan <- num
  }
 }
 // 处理结束之后 退出
 exitChan <- true
 fmt.Println("consumer goroutine 退出啦")
}
func main() {
 intChan := make(chan int, 10000)
 exitChan := make(chan bool, 4)
 primeChan := make(chan int, 5000)
 // 起一个goroutine生产数据
 go producer(intChan)
 // 起四个goroutine消费数据
 for i:=0; i<4; i++ {
  go consumer(intChan, primeChan, exitChan)
 }
 // 起一个goroutine等待消费者goroutine退出 并且退出之后关闭结果chan(primeChan)
 // 这里可以在main goroutine中直接同步等待退出,但是考虑到并发特性,还是go func出去等,不要阻塞main goroutine
 go func() {
  for i:=0; i<4; i++ {
   <- exitChan
  }
  close(primeChan)
 }()
    //main goroutine 打印结果
    for v := range primeChan {
     fmt.Println("main goroutine 接收到的素数是:", v)
 }
 fmt.Println("main goroutine 退出啦")
}


4. 小结


  • 谁负责生产数据到chan,谁就负责关闭chan
  • 谁最后处理完chan中数据,就应该通知调用方自己退出了
  • main goroutine一定是程序最后一个goroutine退出的


- END -

相关文章
|
6天前
|
安全 大数据 Go
深入探索Go语言并发编程:Goroutines与Channels的实战应用
在当今高性能、高并发的应用需求下,Go语言以其独特的并发模型——Goroutines和Channels,成为了众多开发者眼中的璀璨明星。本文不仅阐述了Goroutines作为轻量级线程的优势,还深入剖析了Channels作为Goroutines间通信的桥梁,如何优雅地解决并发编程中的复杂问题。通过实战案例,我们将展示如何利用这些特性构建高效、可扩展的并发系统,同时探讨并发编程中常见的陷阱与最佳实践,为读者打开Go语言并发编程的广阔视野。
|
5天前
|
Kubernetes Go Docker
在K8s编程中如何使用Go
一文带你了解在K8s编程中如何使用Go
23 3
|
16天前
|
消息中间件 缓存 Kafka
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
|
16天前
|
缓存 NoSQL Redis
go-zero微服务实战系列(七、请求量这么高该如何优化)
go-zero微服务实战系列(七、请求量这么高该如何优化)
|
16天前
|
缓存 NoSQL 数据库
go-zero微服务实战系列(五、缓存代码怎么写)
go-zero微服务实战系列(五、缓存代码怎么写)
|
11天前
|
Java 数据库连接 数据库
携手前行:在Java世界中深入挖掘Hibernate与JPA的协同效应
【8月更文挑战第31天】Java持久化API(JPA)是一种Java规范,为数据库数据持久化提供对象关系映射(ORM)方法。JPA定义了实体类与数据库表的映射及数据查询和事务控制方式,确保不同实现间的兼容性。Hibernate是JPA规范的一种实现,提供了二级缓存、延迟加载等丰富特性,提升应用性能和可维护性。通过结合JPA和Hibernate,开发者能编写符合规范且具有高度可移植性的代码,并利用Hibernate的额外功能优化数据持久化操作。
27 0
|
11天前
|
监控 Devops 测试技术
|
14天前
|
安全 Java 测试技术
Go 高性能编程心法探秘
文章深入探讨了Go语言在高性能编程中的各种技巧,包括常用数据结构的使用、内存管理、并发编程策略,以及如何通过减少锁的使用、有效利用sync包中的工具来优化程序性能。
10 0
|
14天前
|
Go C语言
Go语言:新时代的编程英雄,让你的代码驾驭未来!
【8月更文挑战第29天】Go,或称Golang,是由谷歌开发的一种静态强类型的编译语言,旨在融合C语言的高效性和高级语言的易用性。它简洁、优雅,广泛应用于高性能服务器和网络应用开发。本文将通过环境搭建、Hello World示例、变量、常量、控制结构、函数、结构体、接口及错误处理等示例,带你快速入门Go语言,领略其简洁高效的魅力,激发你的编程热情。
24 0
|
16天前
|
消息中间件 SQL 关系型数据库
go-zero微服务实战系列(十、分布式事务如何实现)
go-zero微服务实战系列(十、分布式事务如何实现)