(四十四)golang--協程(goroutine)和管道(channel)相結合實例

統計1-8000之間的素數。框架

總體框架:spa

 

說明:有五個協程,三個管道。其中一個協程用於寫入數字到intChan管道中,另外四個用於取出intChan管道中的數字並判斷是不是素數,而後將素數寫入到primeChan管道中,最後若是後面四個協程哪個工做完了,就寫入一個true到exit管道中,最後利用循環判斷這四個協程是否都完成任務,並退出。線程

main.gocode

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("使用協程耗費時間:%s\n", cost)
        close(primeChan)
    }()

    for {
        // res, ok := <-primeChan
        _, ok := <-primeChan
        if !ok {
            break
        }
        //在這裏計算已經完成了,爲了計算時間,註釋掉了打印的操做
        // fmt.Printf("素數=%d\n", 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)
}

最後運行一下看看結果。blog

使用協程的方法的確是要比使用傳統的方法要快的,有其是在數據量進一步的增大時。至此,一個管道和協程的實例就算完成了, it

相關文章
相關標籤/搜索