278_尚硅谷_协程求素数的代码效率测试
1.goroutine 和 channel 结合
2.协程求素数的代码效率测试_代码
package main
import (
"fmt"
"time"
)
// * 2. 开启一个putNum 协程, 向管道 intChan 写入8000个整数
func putNum(intChan chan int) {
fmt.Println("=============== writeData start ===============")
for i := 1; i <= 500000; i++ {
// * 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, 20000) // 素数(prime)数量的结果管道
exitChan := make(chan bool, 4) // 标识退出的管道 4个
// todo 统计时间
start := time.Now().Unix()
// * 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
}
end := time.Now().Unix()
fmt.Println("使用协程耗时= ", end-start)
// 当从exitChan 取出了4个结果,就可以放心的关闭primeChan管道
close(primeChan)
}()
// * 5. 遍历primeChan, 把结果取出
for {
_, ok := <-primeChan
if !ok {
break
}
// 将结果输出
// fmt.Printf("素数= %d\n", res)
}
fmt.Println("main线程退出")
}
3.协程求素数的代码效率测试_运行结果
4.传统写法,查看运行时间_代码
package main
import (
"fmt"
"time"
)
// todo 传统写法,查看运行时间
func main() {
// todo 统计时间
start := time.Now().Unix()
for num := 1; num <= 500000; num++ {
// 假设是素数, 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
}
}
end := time.Now().Unix()
fmt.Println("不使用协程耗时= ", end-start)
}
5.传统写法,查看运行时间_运行结果,是协程运行时间的4倍,根据CPU数量开了4个协程
浙公网安备 33010602011771号