Golang多线程排序实现快速高效地处理大规模数据

 更新时间:2023年05月11日 10:10:20   作者:Luyoungs  
Golang多线程排序是一种快速高效地处理大规模数据的方法,通过使用Golang的协程和通道,可以将排序任务分配到多个线程中并行处理,提高了排序的效率和速度,需要详细了解可以参考下文

前言

本案例实现一个多线程排序算法,能够对给定的整数数组进行排序,使用 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

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

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

相关文章

  • 使用golang脚本基于kubeadm创建新的token(问题分析)

    使用golang脚本基于kubeadm创建新的token(问题分析)

    这篇文章主要介绍了使用golang脚本基于kubeadm创建新的token(问题分析),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-10-10
  • 如何使用腾讯云go sdk 查询对象存储中最新文件

    如何使用腾讯云go sdk 查询对象存储中最新文件

    这篇文章主要介绍了使用腾讯云go sdk 查询对象存储中最新文件,这包括如何创建COS客户端,如何逐页检索对象列表,并如何对结果排序以找到最后更新的对象,我们还展示了如何优化用户体验,通过实时进度更新和检索多个文件来改进程序,需要的朋友可以参考下
    2024-03-03
  • 解决电脑用GoLand太卡将VsCode定制成Go IDE步骤过程

    解决电脑用GoLand太卡将VsCode定制成Go IDE步骤过程

    这篇文章主要为大家介绍了解决电脑用GoLand太卡,将VsCode定制成Go IDE步骤过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • golang 实现时间滑动窗口的示例代码

    golang 实现时间滑动窗口的示例代码

    滑动时间窗口就是把一段时间片分为多个样本窗口,可以通过更细粒度对数据进行统计,这篇文章主要介绍了golang 实现时间滑动窗口,需要的朋友可以参考下
    2022-10-10
  • Go 实现 Nginx 加权轮询算法的方法步骤

    Go 实现 Nginx 加权轮询算法的方法步骤

    本文主要介绍了Go 实现 Nginx 加权轮询算法的方法步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • 基于go+vue实现的golang每日新闻数据浏览与检索平台(推荐)

    基于go+vue实现的golang每日新闻数据浏览与检索平台(推荐)

    gonews是基于 go+vue 实现的golang每日新闻浏览与检索平台,本文通过实例代码给大家讲解,介绍的非常详细,具有参考借鉴价值,需要的朋友参考下吧
    2018-01-01
  • golang 解析word文档操作

    golang 解析word文档操作

    这篇文章主要介绍了golang 解析word文档操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • go语言开发环境安装及第一个go程序(推荐)

    go语言开发环境安装及第一个go程序(推荐)

    这篇文章主要介绍了go语言开发环境安装及第一个go程序,这篇通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-02-02
  • golang类型推断与隐式类型转换

    golang类型推断与隐式类型转换

    这篇文章主要介绍了golang类型推断与隐式类型转换,golang类型推断可以省略类型,像写动态语言代码一样,让编程变得更加简单,同时也保留了静态类型的安全性
    2022-06-06
  • 基于go interface{}==nil 的几种坑及原理分析

    基于go interface{}==nil 的几种坑及原理分析

    这篇文章主要介绍了基于go interface{}==nil 的几种坑及原理分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04

最新评论