277_尚硅谷_协程求素数的代码实现
1.协程求素数的实现_代码
package main
import (
"fmt"
"time"
)
// * 2. 开启一个putNum 协程, 向管道 intChan 写入8000个整数
func putNum(intChan chan int) {
fmt.Println("=============== writeData start ===============")
for i := 1; i <= 8000; i++ {
// for i := 1; i <= 80; i++ { // 暂定用80
// * 2.1 放入数据
intChan <- i
}
fmt.Println("=============== writeData end ===============")
// * 2.2 放入数据结束后,关闭管道,关闭管道后
close(intChan)
}
// * 3. 开启4个协程,从 intChan 取出数据,并判断是否为素数,就放到primeChan
func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {
// 使用for循环, 从intChan管道中取值
var flag bool //
for {
//! 取值时需要休眠, 原因在于取的过快,导致还没存入就开始取值,导致判断取不到的情况
time.Sleep(time.Millisecond * 10)
// intChan管道取值
num, ok := <-intChan
// 如果管道取不到了值,终止管道取值循环
if !ok {
break
}
// 假设是素数, flag为true
flag = true
// 判断num是不是素数(prime) 素数只能被1和本身整除
for i := 2; i < num; i++ {
if num%i == 0 { // num % 2的余数如果是0, 说明该num不是素数
flag = false
break
}
}
// 如果是素数, 将num这个数就放入到primeChan
if flag {
primeChan <- num
}
}
fmt.Println("有一个primeNum 协程因为取不到数据, 退出")
// ! 注: 这里不能关闭 primeChan, 会有其它程序在处理
// 向exitChan 写入 true, 执行log操作
exitChan <- true
}
func main() {
// * 1. 创建3个管道
intChan := make(chan int, 1000)
primeChan := make(chan int, 1000) // 素数(prime)数量的结果管道
exitChan := make(chan bool, 4) // 标识退出的管道 4个
// * 2. 开启一个协程, 向 intChan 填写8000个数
go putNum(intChan)
// * 3. 开启4个协程,从 intChan 取出数据,并判断是否为素数,就放到primeChan
for i := 0; i < 4; i++ {
go primeNum(intChan, primeChan, exitChan)
}
// * 4. 使用一个匿名函数, 将如下主线程处理运行起来
go func() {
// 主线程处理,从exitChan管道中有4个true记录,说明4个协程全部处理完毕
for i := 0; i < 4; i++ {
// 只需要从exitChan管道里取4个数据,数量够即可,因为上面只有执行成功时才会写入true
// 不成功,不写东西
<-exitChan
}
// 当从exitChan 取出了4个结果,就可以放心的关闭primeChan管道
close(primeChan)
}()
// * 5. 遍历primeChan, 把结果取出
for {
res, ok := <-primeChan
if !ok {
break
}
// 将结果输出
fmt.Printf("素数= %d\n", res)
}
fmt.Println("main线程退出")
}
2.协程求素数的实现_运行结果
浙公网安备 33010602011771号