package main
import (
"sync"
"time"
)
var wg sync.WaitGroup
// 向数字管道内存放数据
func putNum(intChan chan int) {
for i := 2; i < 300000; i++ {
intChan <- i
}
close(intChan)
wg.Done()
}
// 从数字管道中取值判断是否素数并保存到素数管道
func primeNum(intChan chan int, primeChan chan int, doneChan chan int) {
for num := range intChan {
res := true
for i := 2; i < num; i++ {
if num%i == 0 {
res = false
break
}
}
if res {
primeChan <- num
}
}
wg.Done()
// 记录协程执行完毕
doneChan <- 1
}
// 打印数据
func printNum(primeChan chan int) {
// for data := range primeChan {
// println(data)
// }
wg.Done()
}
func main() {
start := time.Now().Unix()
// 定义存放 1 - 12万的数字的管道
intChan := make(chan int, 1000)
// 存放素数的管道
primeChan := make(chan int, 50000)
// 存放数据
wg.Add(1)
go putNum(intChan)
// 从数字管道中取值判断是否素数并保存到素数管道
// 开启多个协程
// 此处开启了多个协程向管道 primeChan 写入数据
// 而 打印数据 函数需要关闭管道, 那么如何关闭管道呢?
// 当 16个协程执行完毕时关闭管道
// 利用一个管道记录协程是否执行完毕
doneChan := make(chan int, 16)
for i := 0; i < 16; i++ {
wg.Add(1)
go primeNum(intChan, primeChan, doneChan)
}
// 打印数据
wg.Add(1)
go printNum(primeChan)
// 判断16次协程是否执行完毕
go func() {
for i := 0; i < 16; i++ {
<-doneChan
}
// 关闭素数统计管道
close(primeChan)
close(doneChan)
}()
wg.Wait()
// 程序结束
println("运行时间 :", time.Now().Unix()-start)
println("素数个数 :", len(primeChan))
}
运行结果
运行时间 : 2 秒
素数个数 : 25997
比没有开启协程时运行效率明显提高 ( 同一台机器非协程模式需要 13 秒 )。