素数筛

素数筛【并发特性】(个人理解)

// 返回生成自然数序列的管道: 2, 3, 4, ...
func GenerateNatural() chan int {
    ch := make(chan int)
    go func() {
        for i := 2; ; i++ {
            ch <- i
        }
    }()
    return ch
}

// 管道过滤器: 删除能被素数整除的数
func PrimeFilter(in <-chan int, prime int) chan int {
    out := make(chan int)
    go func() {
        for {
            if i := <-in; i%prime != 0 {
                out <- i
            }
        }
    }()
    return out
}

func main() {
    ch := GenerateNatural() // 自然数序列: 2, 3, 4, ...
    for i := 0; i < 10; i++ {
        prime := <-ch // 新出现的素数
        fmt.Printf("%v: %v\n", i+1, prime)
        ch = PrimeFilter(ch, prime) // 基于新素数构造的过滤器
    }
}
GenerateNatural()函数,用于生成自然数序列,并返回一个自动获取自然数的管道ch
PrimeFilter()函数,每次生成新的管道out,用于放置非本素数的倍数的自然数

main函数解释

1. main函数开启,执行在goroutine1
2. 调用GenerateNatural()函数,生成goroutine2,用于生成生成自然数序列,并把自然数放到为ch的管道用于传输
3. 第一次ch管道传输过来的是2,为素数,直接输出
4. 调用PrimeFilter()函数,生成goroutine3一直监听ch管道的数据,生成out1管道,用于放置大于2的非2的倍数的自然数
5. 返回out1管道,用于获取大于2素数,并把out1设置成==当前管道==
6. 第4步的goroutine3,一直在读取ch管道的数据,读到数字3,判断不为2的倍数,把数字3放置到out1管道
7. 当前管道获取到数据,循环继续
8. 重复第4步,生成goroutine4,监听的是out1的管道的数据(即将不是2的倍数数据接手过来,判断是否为3的倍数),生成out2管道,用于放置大于3的非3的倍数的自然数
9. 返回out2管道,用于获取大于3的素数,并把out2设置成当前管道
10. 第4步的goroutine3,一直在读取ch管道的数据,读到数字4,判断为2的倍数,直接跳过
11. 继续读取到5,判断不为2的倍数,将5放置到out1管道,
12. 第8步的goroutine4,一直在读取out1管道的数据,读取到数字5,判断不为3的倍数,放置到out2
13. 当前管道获取到数据,循环继续
14. 重复第4步,生成goroutine5,监听的是out2的管道的数据(即将不是3的倍数数据接手过来,判断是否为5的倍数),生成out3管道,用于放置大于5的非5的倍数的自然数
15. ......循环

所以整个素数筛就是从goroutine2(筛选非2倍数)=>goroutine4(筛选非3倍数)=>goroutine5(筛选非5倍数),组成了一条链表式的素数筛,整个流程如下图

素数筛图示

你可能感兴趣的:(素数筛)