当前位置: 首页 > news >正文

go协程奇偶打印和交替打印ABC

前言

这个题目算是面试常问了,之前用JAVA多线程也经常问到 Java多线程打印ABC。

奇偶打印

代码直接参考 https://blog.csdn.net/nxj_climb/article/details/133035078, 可能有些小更改 但大差不差。
就是使用channel对协程读和写进行阻塞来保证时序。
(note: 也可以参照上述博客的地址,另一位博主也show了一下单个channel打印奇偶的写法,不过为了普适性,方便应对面试扩展题,还是掌握一下通用一些的写法吧。

packagemainimport("fmt""sync")funcprintNumber(nint){c1:=make(chanbool,1)c2:=make(chanbool,1)wg:=sync.WaitGroup{}wg.Add(2)gofunc(nint){deferwg.Done()fori:=1;i<=n;i+=2{<-c1 fmt.Println(fmt.Sprintf("A %d",i))c2<-true}}(n)gofunc(nint){deferwg.Done()fori:=2;i<=n;i+=2{<-c2 fmt.Println(fmt.Sprintf("B %d",i))c1<-true}}(n)// 启动第一个goroutine,因为从1开始,所以先启动打印奇数的协程c1<-truewg.Wait()}funcmain(){printNumber(10)}

PrintABC

模仿刚刚的策略,书写printABC的策略。使用三个通道进行阻塞读写

缓冲channel

packagemainimport("fmt""sync")// 交替打印n次ABCfuncPrintABC(nint){c1:=make(chanbool,1)// 记得一定是一个,不然没法阻塞写c2:=make(chanbool,1)c3:=make(chanbool,1)wg:=sync.WaitGroup{}wg.Add(3)// 3个协程gofunc(nint){deferwg.Done()fori:=1;i<=n;i++{<-c1 fmt.Print(fmt.Sprintf("%d A",i))// 为了不去数多少个,加个数字吧// fmt.Print("A")c2<-true}}(n)gofunc(nint){deferwg.Done()fori:=1;i<=n;i++{<-c2 fmt.Print("B")c3<-true}}(n)gofunc(nint){deferwg.Done()fori:=1;i<=n;i++{<-c3 fmt.Println("C")c1<-true}}(n)c1<-truewg.Wait()}funcmain(){PrintABC(10)}



封装一下

packagemainimport("fmt""sync")// Printer 结构体封装打印逻辑typePrinterstruct{chars[]string// 要打印的字符countint// 每个字符打印次数chs[]chanstruct{}// 控制通道wg sync.WaitGroup totalRoundsint// 总轮次}// NewPrinter 创建新的打印机funcNewPrinter(chars[]string,countint)*Printer{n:=len(chars)chs:=make([]chanstruct{},n)fori:=rangechs{chs[i]=make(chanstruct{})}return&Printer{chars:chars,count:count,chs:chs,totalRounds:len(chars)*count,}}// Start 启动所有打印协程func(p*Printer)Start(){n:=len(p.chars)p.wg.Add(n)// 为每个字符创建一个协程fori:=0;i<n;i++{gop.printWorker(i)}// 启动第一个协程p.chs[0]<-struct{}{}p.wg.Wait()fmt.Println()}// printWorker 打印工作协程func(p*Printer)printWorker(idint){deferp.wg.Done()// 计算该协程需要打印的次数rounds:=p.totalRounds/len(p.chars)forj:=0;j<rounds;j++{<-p.chs[id]// 等待自己的信号fmt.Print(p.chars[id])// 打印字符nextID:=(id+1)%len(p.chars)// 计算下一个协程的IDifj<rounds-1||nextID!=0{// 如果不是最后一轮或最后一个字符p.chs[nextID]<-struct{}{}// 通知下一个协程}}}funcmain(){// 示例1:打印 ABC 10次fmt.Print("ABC打印10次: ")printer1:=NewPrinter([]string{"A","B","C"},10)printer1.Start()// 示例2:打印 1234 5次fmt.Print("1234打印5次: ")printer2:=NewPrinter([]string{"1","2","3","4"},5)printer2.Start()// 示例3:打印 XYZ 3次fmt.Print("XYZ打印3次: ")printer3:=NewPrinter([]string{"X","Y","Z"},3)printer3.Start()}

ABC打印10次: ABCABCABCABCABCABCABCABCABCABC
1234打印5次: 12341234123412341234
XYZ打印3次: XYZXYZXYZ



sync.cond

packagemainimport("fmt""sync")funcmain(){varmu sync.Mutex cond:=sync.NewCond(&mu)current:=0// 0-A, 1-B, 2-Ccount:=10done:=falsevarwg sync.WaitGroup wg.Add(3)// 协程 Agofunc(){deferwg.Done()fori:=0;i<count;i++{mu.Lock()forcurrent!=0&&!done{cond.Wait()}fmt.Print("A")current=1mu.Unlock()cond.Broadcast()}}()// 协程 Bgofunc(){deferwg.Done()fori:=0;i<count;i++{mu.Lock()forcurrent!=1&&!done{cond.Wait()}fmt.Print("B")current=2mu.Unlock()cond.Broadcast()}}()// 协程 Cgofunc(){deferwg.Done()fori:=0;i<count;i++{mu.Lock()forcurrent!=2&&!done{cond.Wait()}fmt.Print("C")ifi==count-1{done=true}current=0mu.Unlock()cond.Broadcast()}}()wg.Wait()fmt.Println()}
http://www.jsqmd.com/news/472633/

相关文章:

  • 探索ccv:一个轻量级且功能强大的计算机视觉库
  • KCD Beijing + vLLM 2026 全议程公布:30+ 技术分享,AI × 云原生 × vLLM 一次看够
  • Kafka 如何解决消息堆积问题?
  • 腾讯AI布局:QClaw登场,元宝何去何从?
  • Android开发者必备:TooLargeTool日志分析实战教程
  • 【亲测免费】 mergerfs 项目使用教程
  • 汇智信科-飞行讲评系统
  • AI应用新趋势:中国崛起与全球市场割裂
  • 项目推荐:Stable Diffusion WebUI Colab
  • Kafka 消息堆积的原因有哪些?
  • 微软Copilot惨败,Anthropic能救场吗?
  • Logstash:强大的数据处理管道,助力日志管理与分析
  • 2024年必收藏的开发者资源:dev-resources精选工具TOP50
  • 2026年广东AI智能测试标杆厂家最新推荐:AI智能信创测试公司、AI智能测试管理公司、AI智能自动化测试公司、AI智能性能测试公司、AI智能接口测试公司广州掌动智能 - 海棠依旧大
  • AI短剧来袭:真人剧会被全面替代吗?
  • 别再乱用ScrollViewer了!WPF滚动容器与布局控件的正确搭配指南
  • 深入理解粤语编程编译器:从Python转换到LLVM执行
  • Symfony Translation终极指南:构建React+Capacitor跨平台多语言应用
  • Makefile实战:如何用5分钟搞定动态库(.so)的自动化编译与调用
  • 手把手教你用Wireshark调试Robosense激光雷达网络配置(附静态IP设置技巧)
  • 【C语言入门级教学】C语言常见概念1
  • ubuntu 22下android 源码编译/烧录-2
  • DeepMotion实战:用Python调用API实现抖音风格特效动画(附GitHub源码)
  • SHT11温湿度传感器实战:从硬件连接到数据读取的完整指南(附代码)
  • Tkinter Canvas高阶技巧:用数学函数绘制动态五角星和自定义图形
  • 【人工智能】Mixture of Experts(MoE,混合专家模型/系统):大模型时代的智能分工架构,是一种通过动态分配子网络(专家)处理不同输入特征的机器学习技术,旨在提升模型效率与性能。
  • YUV420 vs YUV422 vs RGB565:移动端图像处理中的格式选择与性能优化
  • Kafka 如何保证消息可靠性?
  • 5分钟搞定RealSense D435i手部追踪:MediaPipe实战教程(附完整代码)
  • 避坑指南:uniapp中scroll-view滚动定位的那些坑(商品分类案例详解)