tft每日頭條

 > 生活

 > golang面試知識點

golang面試知識點

生活 更新时间:2024-12-14 14:30:54
題目

計算出50萬以内的素數。用普通方法後,再考慮用goroutine加快處理速度。

  • 要求
  1. 使用普通方法進行計算。
  2. 利用goroutine多協程方式實現。
  3. 對比兩種方法的時間效率差。

說明: 本例是一個使用goroutine與channel比較綜合的題目,有一定複雜度,需要先仔細分析,有思路後才上代碼。

代碼實現
  • 普通方式

即輪詢1-50萬的正整數,依次計算出素數

package main import ( "fmt" "time" ) // 判斷一個數是否是素數 func isPrieme(num int) bool { for i:=2;i<num;i { if num%i == 0 { return false } } return true } func main() { //ch := make(chan int) //創建一個無緩存channel start := time.Now().Unix() for i:=1;i<500000;i { if isPrieme(i) { //fmt.Println(i) } } totolTime := time.Now().Unix() - start fmt.Println("用時(s):",totolTime) }

  • 執行結果

(base) ➜ study go run test.go 用時(s): 71

使用多協程方式實現
  • 思路分析

需要借用三個管道來完成題目

1. 用一個協程,将50萬個數放入一個管道inChannel中,放入完成後關閉管道。

2. 啟動多個協程,同時從inChannel中取數據,并判斷是否為素數,如果是素數則将結果放入另一個管道 resultChannel

3. 當某個協程完成操作後,放入一個标記位True,到一個叫flagChannel的管道。這個channel用于标識某個協程已經完成退出,當flagChannel管道内的元素個數等于啟動的協程數量時,表示所有協程都完成并退出了。

golang面試知識點(golanggoroutine與channel經典練習題)1

package main import ( "fmt" "runtime" "time" ) /* 1. 用一個協程,将1-100個數放入一個channel inChannel中。 2. 啟動10個協程,同時從inChannel中取數據,并計算n的平方,将結果值放入一個新的channel resultChannel 3. 10個協程,寫完後,放入一個标記位True,到标記channel flagChannel,這個channel用于标識已經完成數據處理 4. 當标記位個數為10時,表示10個協程都不能取數據了(inChannel已經空了),這時才可以關閉管道resultChannel */ // 判斷一個數是否是素數 func isPrieme(num int) bool { for i:=2;i<num;i { if num%i == 0 { return false } } return true } func writeData(inChannel chan int){ // 寫入100個數據到inChannel for i:=1;i<=500000;i { inChannel <- i //fmt.Println("寫入數據data= ",i) } // 寫入完成後關閉inChannel close(inChannel) } func readAndDealData(inChannel chan int,resultChannel chan int, flagChannel chan bool){ fmt.Println("啟動一個新的協程------------") for { // 從inChannel中拿數據 data,ok := <-inChannel if ok { // 如果拿到數據 //fmt.Println("拿到數據data= ",data) // 對拿到的數據進行處理 if isPrieme(data) { // 處理完畢後,将結果放入結果管道resultChannel resultChannel<- data //fmt.Println("素數=",data) } }else { // 如果沒有從inChannel拿到數據,表示這個協程的工作已經結束 break } } // 拿不到數據則表示這個協程已經處理完成,則放一個标記位到flagChannel管道 flagChannel <- true } func main(){ fmt.Println("hello world") // 設置可用處理器個數 cpuNum := runtime.NumCPU() runtime.GOMAXPROCS(cpuNum-1) fmt.Println("cpuNum=",cpuNum) // 啟動協程的數量 gorutNum := 8 //1 --- 69,2 --- 35s,4 --- 21 // 保存輸入數據 inChannel := make(chan int, 10000) // 保存計算結果 resultChannel := make(chan int, 100000) // 保存退出标記位,如果flagChannel一旦有數據,标識已經處理完成,主進程檢查到後就退出 flagChannel := make(chan bool, gorutNum) start := time.Now().Unix() // 啟動寫數據的協程 go writeData(inChannel) // 啟動10個同時拿數據并處理數據的協程 for i:=0;i<gorutNum;i { go readAndDealData(inChannel,resultChannel,flagChannel) } // 阻塞主進程,等待所有協程完成 for i:=0;i<gorutNum;i { _,ok := <-flagChannel if ok { // 一旦有數據,表示所有協程已經處理完成 fmt.Println("一個協程處理完畢!") } } close(flagChannel) fmt.Println("Done!") totolTime := time.Now().Unix() - start fmt.Println("總共用時(s): ", totolTime ) }

  • 執行結果

(base) ➜ 04 go run main.go hello world cpuNum= 8 啟動一個新的協程------------ 啟動一個新的協程------------ 啟動一個新的協程------------ 啟動一個新的協程------------ 啟動一個新的協程------------ 啟動一個新的協程------------ 啟動一個新的協程------------ 啟動一個新的協程------------ 一個協程處理完畢! 一個協程處理完畢! 一個協程處理完畢! 一個協程處理完畢! 一個協程處理完畢! 一個協程處理完畢! 一個協程處理完畢! 一個協程處理完畢! Done! 總共用時(s): 15

可以看出,使用多協程方式來計算50萬以内的素數隻用了15秒

結果對比

測試機

普通方式

多協程方式

macbook i7

71秒

15秒

所以看處理大數據計算密集時可以考慮用goroutine方式。但是從編碼難度上考慮,goroutine方式要比普通方式要大一些。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved