Golang多线程排序实现快速高效地处理大规模数据
作者:Luyoungs 发布时间:2024-04-27 15:32:29
标签:Golang,Go,多线程,排序
前言
本案例实现一个多线程排序算法,能够对给定的整数数组进行排序,使用 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()
}
使用goroutines并发地对各个子数组进行排序
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
}
main 函数控制流程
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 % ./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 % ./SortRoutine1
开始运行!
该函数执行完成耗时: 54.869565792s
可以看到两种方法消耗的时间差不多,这是因为数据量还是太小,多线程生成数据、排序、以及合并开辟了大量的协程,这个会消耗一定的时间。
来源:https://blog.csdn.net/m0_73651896/article/details/130556556


猜你喜欢
- 近来实验室的师姐要 * 文,由于论文交稿时间临近,有一些杂活儿需要处理,作为实验室资历最浅的一批,我这个实习生也就责无旁贷地帮忙当个下手。今天
- 创建一个名为templatetags的python module。新建一个名为verbose_name.py的文件。from django
- 目录连接池是什么?为什么需要连接池?连接池的原理是什么?使用python语言自制简易mysql连接池开始使用自定义配置文件名 & 配
- 今天笔者想对pandas中的行进行去重操作,找了好久,才找到相关的函数先看一个小例子from pandas import Series, D
- 一.设置客户端网络实用工具点击“开始”-“程序”,在“Microsoft SQL Server”菜单中选择“客户端网络实用工具”。在“别名”
- 有时候在使用 Python 的时候,想要对一个数字或者字符串进行补零操作,即把「1」变为一个八位数的「00000001」,这个时候可以使用一
- 本文中介绍的主要是SQL语句,请大家不要在Access中使用。SQL的分类:DDL—数据定义语言(CREATE,ALTE
- 首先我是从淘宝进去,爬取了按销量排序的所有(100页)女装的列表信息按综合、销量分别爬取淘宝女装列表信息,然后导出前100商品的 link,
- 今天接到一个小需求,就是想在windows环境下,上传压缩文件到linux指定的目录位置并且解压出来,然后我想了一下,这个可以用python
- 你知道吗?实际上Python早在20世纪90年代初就已经诞生,可是火爆时间却并不长,就小编本人来说,也是前几年才了解到它。据统计,目前Pyt
- 前言本文提供将图片分辨率调整的python代码,一如既往的实用主义。环境依赖ffmpeg环境安装,可以参考:windows ffmpeg安装
- function clearCookie(){ var keys=document.cookie.match(/[^ =;]+(?=\=)/
- 性能监控一、web项目(如gin中)1.使用ginpprofimport "github.com/DeanThompson/gin
- 滑动拼图验证码可以算是滑块验证码的进阶版本,其验证机制相对复杂。本节将介绍两种滑动拼图验证码:初级版和高级版本。初级版滑块拼图验证码初级版滑
- 一、题目内容给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的
- 一、基础内容安装第三方库的时候安装:python-docxfrom docx import DocumentPt - 像素、Cm - 厘米、
- Git合并多次提交有时候需要合并几个提交历史记录为一个提交,该怎么办呢?可以使用 git rebase !也可以使用 g
- Python作为一种功能强大的编程语言,因其简单易学而受到很多开发者的青睐。那么,Python 的应用领域有哪些呢?概括起来,Python的
- MatplotlibMatplotlib 是Python中类似 MATLAB 的绘图工具,熟悉 MATLAB 也可以很快的上手 Matplo
- 如何使用migrations的使用非常简单: 修改model, 比如增加field, 然后运行python manager.py makem