Golang多线程排序实现快速高效地处理大规模数据(golang线程安全)这都可以

随心笔谈2年前发布 admin
190 0 0

文章摘要

这篇文章介绍了如何在Go语言中使用goroutine对大规模数据进行多线程排序。文章主要分为以下几个部分: 1. **引言** 介绍了使用goroutine对给定的整数数组进行排序,通过并发优化来提高性能。文章提到使用了一个大小为1亿的数据集,通过100个goroutine来处理随机数生成、排序以及合并排序结果。 2. **实现细节** - **`randProduce`函数**:启动多个goroutine来生成随机数,并将这些随机数发送到一个通道中。 - **`sort0`函数**:启动多个goroutine对生成的随机数进行排序,并将排序后的结果发送到另一个通道中。 - **`mergeAll`函数**:通过多线程实现合并排序结果的过程,最终得到最终的排序结果。 3. **性能比较** 文章比较了多线程方法与单线程方法的性能。结果显示,尽管多线程方法在数据量较小时的执行时间与单线程方法相近,但随着数据量的增加,多线程方法的开销变得明显,导致性能下降。 4. **结论** 文章总结了多线程排序在处理大规模数据时的优势,同时也指出了其在数据量较大时的性能瓶颈。 总结来说,这篇文章通过 goroutine 实现了多线程排序,展示了在Go语言中如何高效地处理大规模数据排序问题。



目录前言随机数生成器使用goroutines并发地对各个子数组进行排序合并已排序的子数组得到最终排序结果main 函数控制流程思路性能比较

本案例实现一个多线程排序算法,能够对给定的整数数组进行排序,使用 goroutines 对其进行并发化优化。

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()
}
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()
}
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
}
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(“该函数执行完成耗时:”, elapsed)
}

本案例采用了两个 channel,分别存储产生的的随机数slice和排好顺序的 slice,每一个 slice大小为 100 万,一共一百个 slice,也就是一亿个数据。

randNums :=make(chan []int, 100)
sortNUms :=make(chan []int, 100)

程序一边产生随机数,一边将产生的随机数randNums发送到 sort 函数进行排序,排好顺序后将数据发送到sortNUms。这两个流程可以并行计算,因此:

go randProduce(randNums, &wg)
go sort0(randNums, sortNUms, &wg)

合并也可以参与到并行计算之中,多加一个信号量就好:

go mergeAll(sortNUms, &wg)

运行结果:

(base) luliang@shenjian Sort % go build SortRoutine.go

(base) luliang@shenjian Sort % https://www.jb51.net/article/SortRoutine

开始运行!

该函数执行完成耗时: 50.317081625s

可以写一个单线程的排序,但是数据产生还是多线程的:

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(“该函数执行完成耗时:”, 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)
}
}

运行结果为:

(base) luliang@shenjian Sort % go build SortRoutine1.go

(base) luliang@shenjian Sort % https://www.jb51.net/article/SortRoutine1

开始运行!

该函数执行完成耗时: 54.869565792s

可以看到两种方法消耗的时间差不多,这是因为数据量还是太小,多线程生成数据、排序、以及合并开辟了大量的协程,这个会消耗一定的时间。

到此这篇关于Golang多线程排序实现快速高效地处理大规模数据的文章就介绍到这了,更多相关Golang多线程排序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:Golang多线程爬虫高效抓取大量数据的利器Golang多线程刷票的实现代码

© 版权声明

相关文章