(四十四)golang--协程(goroutine)和管道(channel)相结合实例

时间:2022-07-23
本文章向大家介绍(四十四)golang--协程(goroutine)和管道(channel)相结合实例,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

统计1-8000之间的素数。

整体框架:

说明:有五个协程,三个管道。其中一个协程用于写入数字到intChan管道中,另外四个用于取出intChan管道中的数字并判断是否是素数,然后将素数写入到primeChan管道中,最后如果后面四个协程哪一个工作完了,就写入一个true到exit管道中,最后利用循环判断这四个协程是否都完成任务,并退出。

main.go

package main

import (
    "fmt"
    "go_code/project_13/test"
    "time"
)

func putNum(intChan chan int) {
    for i := 1; i <= 80000; i++ {
        intChan <- i
    }
    close(intChan)
}

func isPrime(n int) bool {
    //这里本来i只需要到int(math.Sqrt(float64(n))),为了计算时间,就直接设置i-n了
    for i := 2; i <= n; i++ {
        if n%i == 0 {
            return false
        }
    }
    return true
}

func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {
    for {
        // time.Sleep(time.Millisecond * 10)
        num, ok := <-intChan
        if !ok {
            break
        }
        isp := isPrime(num)
        if !isp {
            continue
        } else {
            primeChan <- num
        }
    }
    fmt.Println("有一个协程取不到数据而退出了")
    exitChan <- true
}

func main() {
    intChan := make(chan int, 1000)
    primeChan := make(chan int, 20000)
    exitChan := make(chan bool, 4)
    //记录当前时间
    start := time.Now()
    //开启一个协程
    go putNum(intChan)
    //开启四个协程
    for i := 0; i < 4; i++ {
        go primeNum(intChan, primeChan, exitChan)
    }
    //当四个协程都完成任务后,计算消耗时间,并关闭primeChan管道
    go func() {
        for i := 0; i < 4; i++ {
            <-exitChan
        }
        cost := time.Since(start)
        fmt.Printf("使用协程耗费时间:%sn", cost)
        close(primeChan)
    }()

    for {
        // res, ok := <-primeChan
        _, ok := <-primeChan
        if !ok {
            break
        }
        //在这里计算已经完成了,为了计算时间,注释掉了打印的操作
        // fmt.Printf("素数=%dn", res)
    }
    fmt.Println("主线程退出")
    test.Test()
}

test.go

package test

import (
    "fmt"
    "time"
)

func isPrime(n int) bool {
    for i := 2; i <= n; i++ {
        if n%i == 0 {
            return false
        }
    }
    return true
}
func Test() {
    start := time.Now()
    for i := 1; i < 80000; i++ {
        isPrime(i)
    }
    cost := time.Since(start)
    fmt.Printf("传统方法消耗时间为:%s", cost)
}

最后运行一下看看结果。

使用协程的方法的确是要比使用传统的方法要快的,有其是在数据量进一步的增大时。至此,一个管道和协程的实例就算完成了,