Golang多線程排序?qū)崿F(xiàn)快速高效地處理大規(guī)模數(shù)據(jù)
前言
本案例實現(xiàn)一個多線程排序算法,能夠?qū)o定的整數(shù)數(shù)組進行排序,使用 goroutines 對其進行并發(fā)化優(yōu)化。
隨機數(shù)生成器
func randProduce(randNums chan []int, wg *sync.WaitGroup) { for i := 0; i < 100; i++ { go rand1(randNums, wg) } } func rand1(randNums chan []int, wg *sync.WaitGroup) { r := rand.New(rand.NewSource(time.Now().Unix())) int1000 := make([]int, 1000000) for i := 0; i < 1000000; i++ { int1000[i] = r.Intn(1000000) } randNums <- int1000 wg.Done() }
使用goroutines并發(fā)地對各個子數(shù)組進行排序
func sort0(randNums chan []int, sortNums chan []int, wg *sync.WaitGroup) { for i := 0; i < 100; i++ { go sort2(randNums, sortNums, wg) } } func sort2(randNums chan []int, sortNums chan []int, wg *sync.WaitGroup) { int1000_Old := <-randNums sort.Ints(int1000_Old) sortNums <- int1000_Old wg.Done() }
合并已排序的子數(shù)組得到最終排序結(jié)果
func mergeAll(sortNums chan []int, wg *sync.WaitGroup) []int { defer wg.Done() temp2 := <-sortNums var temp1 []int for i := 1; i <= 99; i++ { temp1 = make([]int, 1000000*i+1000000) copy(temp1, temp2) temp1 = merge(temp1, 1000000*i+1000000, <-sortNums, 1000000) temp2 = make([]int, 1000000*i+1000000) copy(temp2, temp1) } return temp2 } func merge(nums1 []int, m int, nums2 []int, n int) []int { temp := make([]int, m) copy(temp, nums1) t, j := 0, 0 //t為temp的索引,j為nums2的索引 for i := 0; i < len(nums1); i++ { if t >= len(temp) { nums1[i] = nums2[j] j++ continue } if j >= n { nums1[i] = temp[t] t++ continue } if nums2[j] <= temp[t] { nums1[i] = nums2[j] j++ } else { nums1[i] = temp[t] t++ } } return nums1 }
main 函數(shù)控制流程
func main() { fmt.Println("開始運行!") start := time.Now() // 獲取當前時間 wg := sync.WaitGroup{} wg.Add(201) randNums := make(chan []int, 100) sortNUms := make(chan []int, 100) go randProduce(randNums, &wg) go sort0(randNums, sortNUms, &wg) go mergeAll(sortNUms, &wg) wg.Wait() // fmt.Println(l) elapsed := time.Since(start) fmt.Println("該函數(shù)執(zhí)行完成耗時:", elapsed) }
思路
本案例采用了兩個 channel,分別存儲產(chǎn)生的的隨機數(shù)slice和排好順序的 slice,每一個 slice大小為 100 萬,一共一百個 slice,也就是一億個數(shù)據(jù)。
randNums := make(chan []int, 100) sortNUms := make(chan []int, 100)
程序一邊產(chǎn)生隨機數(shù),一邊將產(chǎn)生的隨機數(shù)randNums發(fā)送到 sort 函數(shù)進行排序,排好順序后將數(shù)據(jù)發(fā)送到sortNUms。這兩個流程可以并行計算,因此:
go randProduce(randNums, &wg) go sort0(randNums, sortNUms, &wg)
合并也可以參與到并行計算之中,多加一個信號量就好:
go mergeAll(sortNUms, &wg)
運行結(jié)果:
(base) luliang@shenjian Sort % go build SortRoutine.go
(base) luliang@shenjian Sort % ./SortRoutine
開始運行!
該函數(shù)執(zhí)行完成耗時: 50.317081625s
性能比較
可以寫一個單線程的排序,但是數(shù)據(jù)產(chǎn)生還是多線程的:
package main import ( "fmt" "math/rand" "sort" "time" ) func main() { fmt.Println("開始運行!") start := time.Now() // 獲取當前時間 randNums := make(chan int, 10000) go randProduce1(randNums) randNums1 := make([]int, 100000000) for i := 0; i < 100000000; i++ { randNums1[i] = <-randNums } sort.Ints(randNums1) elapsed := time.Since(start) fmt.Println("該函數(shù)執(zhí)行完成耗時:", elapsed) } func randProduce1(randNums chan int) { for i := 0; i < 10000; i++ { go rand2(randNums) } } func rand2(randNums chan int) { r := rand.New(rand.NewSource(time.Now().Unix())) for i := 0; i < 10000; i++ { randNums <- r.Intn(10000000) } }
運行結(jié)果為:
(base) luliang@shenjian Sort % go build SortRoutine1.go
(base) luliang@shenjian Sort % ./SortRoutine1
開始運行!
該函數(shù)執(zhí)行完成耗時: 54.869565792s
可以看到兩種方法消耗的時間差不多,這是因為數(shù)據(jù)量還是太小,多線程生成數(shù)據(jù)、排序、以及合并開辟了大量的協(xié)程,這個會消耗一定的時間。
到此這篇關(guān)于Golang多線程排序?qū)崿F(xiàn)快速高效地處理大規(guī)模數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Golang多線程排序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go內(nèi)存分配之結(jié)構(gòu)體優(yōu)化技巧
這篇文章主要為大家詳細介紹了Go語言內(nèi)存分配之結(jié)構(gòu)體優(yōu)化技巧的相關(guān)知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2023-11-11Go語言生成UUID的利器(github.com/google/uuid)
UUID是確保每個元素唯一性的重要工具,Go語言雖然在標準庫中沒有直接提供UUID生成功能,但可以通過安裝github.com/google/uuid庫來實現(xiàn),本文就來介紹一下,感興趣的可以了解一下2024-11-11Golang中fsnotify包監(jiān)聽文件變化的原理詳解
Golang提供了一個強大的fsnotify包,它能夠幫助我們輕松實現(xiàn)文件系統(tǒng)的監(jiān)控,本文將深入探討fsnotify包的原理,感興趣的小伙伴可以跟隨小編一起學習一下2023-12-12Golang協(xié)程池gopool設(shè)計與實現(xiàn)
本文主要介紹了Golang協(xié)程池gopool設(shè)計與實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-04-04GoLang調(diào)用鏈可視化go-callvis使用介紹
與鏈路追蹤(Tracing)不同,Tracing關(guān)注復雜的分布式環(huán)境中各個服務節(jié)點間的調(diào)用關(guān)系,主要用于服務治理。而我們本次探索的代碼調(diào)用鏈路則是代碼方法級別的調(diào)用關(guān)系,主要用于代碼設(shè)計2023-02-02Golang 如何實現(xiàn)函數(shù)的任意類型傳參
這篇文章主要介紹了Golang 實現(xiàn)函數(shù)的任意類型傳參操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04