Golang-goroutine实现筛法求素数(附性能测试)

算法原理


参考自今日头条Go建千亿级微服务的实践 举出的goroutine例子

代码

//参数n, 找到(0,n)以内的素数
func get_prime(n int) {
	origin, wait := make(chan int), make(chan struct{})
	go FilterPrime(origin, wait)
	for i := 2; i <= n; i++ {
		origin <- i
	}
	close(origin)
	<-wait #等待同步 防止主线程退出
}

func FilterPrime(seq chan int, wait chan struct{}) {
	prime, ok := <-seq
	if !ok {
		close(wait)
		return
	}
	fmt.Println(prime) //打印素数
	out := make(chan int)
	go FilterPrime(out, wait) //启动另一个goroutine
	for num := range seq {
		if num%prime != 0 {
			out <- num
		}
	}
	close(out)
}

测试

package main

import (
	"fmt"
)

func main() {
	get_prime(10)
}
输出
[ `go run my_prime.go` | done: 5.4524181s ]
	2
	3
	5
	7

Tips: wait变量等待同步

测试代码
```go
package main

import (
	"fmt"
	"time"
)

func main() {
	wait := make(chan struct{})
	go sleepawhile(wait)
	fmt.Println("try to wait")
	<-wait //注释后异常
	fmt.Println("wait Done")
}

func sleepawhile(wait chan struct{}) {
	fmt.Println("go to sleep")
	time.Sleep(3 * time.Second)
	fmt.Println("sleep Done")
	fmt.Println("try to close wait")
	close(wait)
	fmt.Println("close wait Done")
	return
}
正常输出:
	try to wait
	go to sleep
	sleep Done
	try to close wait
	close wait Done
	wait Done
若注释掉 main函数中的"<-wait" 输出:
	try to wait
	wait Done

未等待其他协程运行, 主线程已退出.

channel设置缓冲区

上文中用到的chan都没有缓冲区, 设置缓冲区之后, 一定范围内性能优化明显

package main

import (
	"fmt"
	"time"
)

func main()  {
	testSize := []int{1, 5, 10, 20, 30, 50, 70, 80, 100,200}
	for _, size := range testSize{
		var sum int64
		for t := 0; t< 10; t++{
			sum = sum + Prime(10000, size)
		}
		fmt.Printf("size:%d  avg: %d ms \n",size,sum/10)
	}
}

func Prime(n int, size int) int64 {
	start := time.Now()
	seq, wait := make(chan int, size), make(chan struct{})
	go  PrimeFilter(seq, wait, size)
	for i := 2; i<= n; i++{
		seq <- i
	}
	close(seq)
	<- wait
	timeConsumed := time.Since(start).Nanoseconds()/1000000
	//fmt.Printf("time consumed: %v \n",timeConsumed)
	return timeConsumed
}

func PrimeFilter(seq chan int, wait chan struct{}, size int)  {
	prime, ok := <- seq
	if !ok {
		close(wait)
		return
	}
	//fmt.Println(prime)
	next := make(chan int, size)
	go PrimeFilter(next, wait, size)
	for num := range seq{
		if num%prime != 0{
			next <- num
		}
	}
	close(next)
}

输出:

size:1  avg: 37 ms 
size:5  avg: 25 ms 
size:10  avg: 23 ms 
size:20  avg: 19 ms 
size:30  avg: 18 ms 
size:50  avg: 17 ms 
size:70  avg: 18 ms 
size:80  avg: 19 ms 
size:100  avg: 16 ms 
size:200  avg: 20 ms 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值