278_尚硅谷_协程求素数的代码效率测试

1.goroutine 和 channel 结合1.goroutine 和 channel 结合

2.协程求素数的代码效率测试_代码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.协程求素数的代码效率测试_运行结果3.协程求素数的代码效率测试_运行结果

4.传统写法,查看运行时间_代码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个协程5.传统写法,查看运行时间_运行结果

posted on 2026-03-06 14:22  与太阳肩并肩  阅读(1)  评论(0)    收藏  举报

导航