GO语言并发编程入门:使用管道求单个/多个数组和

2023-02-0410:40:36编程语言入门到精通Comments760 views字数 5541阅读模式

求数组和

需求:定义函数,求一个整数类型切片中所有元素的和。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

示例代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

package main

import "fmt"

// 求和函数
func getArrSum(arr []int){
	sum := 0
	for _,v:= range arr {
		sum+=v
	}
	fmt.Println(sum)
}

func main() {
	// 构建数组
	arr := []int{1, 2}

	// 求和
	getArrSum(arr)
}

使用管道求单个数组和

需求:在上个案例的基础上,使用管道存储求和结果。定义一个管道作为函数的参数,在函数中求和结束后将求和结果写入到管道,在主协程中,读取管道中的结果并打印。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

示例代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

package main

import "fmt"

// 求和函数
func getArrSum(arr []int, c chan<- int){
	sum := 0
	for _,v:= range arr {
		sum+=v
	}
	c<- sum // 将求和结果写入管道
}

func main() {
	// 构建数组
	arr := []int{1, 2}

	// 构建管道
	c := make(chan int)

	// 开启一个协程进行求和
    go getArrSum(arr, c)

	// 等待计算结束后读取求和结果
    sum := <-c

	// 查看结果
	fmt.Println(sum)
}

通过本案例我们应该掌握:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

  • 普通管道的定义方式:chan 类型
  • 只写管道的定义方式:chan<- 类型
  • 只读管道的定义方式:<-chan 类型

使用管道求多个数组和

需求:在之前案例的基础上,实现同时求多个数组的和。比如,求[1,2], [3,4], [5,6]三个数组的和。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

示例代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

package main

import "fmt"

// 求和函数
func getArrSum(arr []int, c chan<- int){
	sum := 0
	for _,v:= range arr {
		sum+=v
	}
	c<- sum // 将求和结果写入管道
}

func main() {
	// 构建数组
	arr1 := []int{1, 2}
	arr2 := []int{3, 4}
	arr3 := []int{5, 6}

	// 构建管道
	c := make(chan int)

	// 开启一个协程进行求和
    go getArrSum(arr1, c)
    go getArrSum(arr2, c)
    go getArrSum(arr3, c)

	// 等待计算结束后读取求和结果
	// 管道写了三次,就要读取三次
	// 这里有一个非常重要的特性,管道是一种类似栈结构,先进后出
	// 所以,我们传入的是arr1、arr2、arr3,得到的却是sum3、sum2、sum1
    sum3 := <-c
    sum2 := <-c
    sum1 := <-c

	// 查看结果
	fmt.Println(sum1, sum2, sum3)
}

案例分析:通过本案例我们应该掌握文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

  • 管道是一种栈结构,先进后出
  • 往管道里面写了多少个数据,就必须要读多少次,否则可能会造成死锁

将单数组拆分多数组并发求和

需求:在之前案例的基础上,我们将一个数组,拆分为多个数组进行并发求和。比如将[12,3,4,5,6],拆分为[1,2], [3,4], [5,6]进行并发求和。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

示例代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

package main

import "fmt"

// 求和函数
func getArrSum(arr []int, c chan<- int){
	sum := 0
	for _,v:= range arr {
		sum+=v
	}
	c<- sum // 将求和结果写入管道
}

func main() {
	// 构建数组
	arr := []int{1,2,3,4,5,6}
	fmt.Println(arr[:2])
	fmt.Println(arr[2:4])
	fmt.Println(arr[4:])

	// 构建管道
	c := make(chan int)

	// 开启一个协程进行求和
    go getArrSum(arr[:2], c)
    go getArrSum(arr[2:4], c)
    go getArrSum(arr[4:], c)

	// 等待计算结束后读取求和结果
	// 管道写了三次,就要读取三次
	// 这里有一个非常重要的特性,管道是一种类似栈结构,先进后出
	// 所以,我们传入的是arr1、arr2、arr3,得到的却是sum3、sum2、sum1
    sum3 := <-c
    sum2 := <-c
    sum1 := <-c

	// 查看结果
	fmt.Println(sum1, sum2, sum3)
}

案例分析:通过本案例我们应该掌握文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

  • Go语言中的数组也叫切片或slice,和Python里面的列表类似,是可以通过切片表达式进行局部访问的
  • 利用切片的特性,我们可以非常轻松的实现将一个大数组拆分为多个小数组,进行并发求和

非并发求数组和

需求:构造一个具有100万个随机10-110范围内的整数的切片,并编写一个求和函数,求切片中所有元素的和,并计算求和需要的时间。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

如何生成随机浮点数

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func main() {
	for i := 0; i < 10; i++ {
		fmt.Println(rand.Float64())
	}
}

如何生成指定范围随机整数

package main

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func main() {
	start := 10
	end := 110
	for i := 0; i < 10; i++ {
		num := rand.Float64()*float64(end) + float64(start)
		numInt := int(math.Floor(num))
		fmt.Println(numInt)
	}
}

如何生成整数切片数组

package main

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func getArr(min, max, length int) (arr []int) {
	for i := 0; i < length; i++ {
		num := rand.Float64()*float64(max) + float64(min)
		numInt := int(math.Floor(num))
		arr = append(arr, numInt)
	}
	return
}

func main() {
	start := 10
	end := 110
	length := 1000000
	arr := getArr(start, end, length)
	fmt.Println(arr[:3], len(arr))
}

如何求切片数组和

package main

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func getArr(min, max, length int) (arr []int) {
	for i := 0; i < length; i++ {
		num := rand.Float64()*float64(max) + float64(min)
		numInt := int(math.Floor(num))
		arr = append(arr, numInt)
	}
	return
}

func getArrSum(arr []int) (sum int) {
	for _, num := range arr {
		sum += num
	}
	return
}

func main() {
	start := 10
	end := 110
	length := 1000000
	arr := getArr(start, end, length)
	sum := getArrSum(arr)
	fmt.Println(sum)
}

如何计算求和时间

package main

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func getArr(min, max, length int) (arr []int) {
	for i := 0; i < length; i++ {
		num := rand.Float64()*float64(max) + float64(min)
		numInt := int(math.Floor(num))
		arr = append(arr, numInt)
	}
	return
}

func getArrSum(arr []int) (sum int) {
	for _, num := range arr {
		sum += num
	}
	return
}

func main() {
	start := 10
	end := 110
	length := 1000000
	arr := getArr(start, end, length)

	startTime := time.Now()
	sum := getArrSum(arr)
	fmt.Println(sum)
	spendTime := time.Since(startTime)
	fmt.Println(spendTime)
}

并发求数组和

需求:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

  • 定义一个方法,接受一个数组和一个管道,对数组求和并将结果写入管道
  • 定义一个方法,接受一个数组,如果数组元素个数大于3个,则将数组等分为3个子数组,并发求和
  • 生成100万个随机10-110之间整数构成的随机数组,并发求和并计算时间

如何将求和结果写入管道

package main

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func getArr(min, max, length int) (arr []int) {
	for i := 0; i < length; i++ {
		num := rand.Float64()*float64(max) + float64(min)
		numInt := int(math.Floor(num))
		arr = append(arr, numInt)
	}
	return
}

func getArrSum(arr []int) (sum int) {
	for _, num := range arr {
		sum += num
	}
	return
}

func writeArrSumChan(arr []int, c chan<- int) {
	c <- getArrSum(arr)
}

func main() {
	start := 10
	end := 110
	length := 1000000
	arr := getArr(start, end, length)

	startTime := time.Now()
	c := make(chan int)
	go writeArrSumChan(arr, c)
	sum := <-c
	fmt.Println(sum)
	spendTime := time.Since(startTime)
	fmt.Println(spendTime)

	// 主动等待结束
	time.Sleep(time.Second * 3)
}

如何并发求和

package main

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func getArr(min, max, length int) (arr []int) {
	for i := 0; i < length; i++ {
		num := rand.Float64()*float64(max) + float64(min)
		numInt := int(math.Floor(num))
		arr = append(arr, numInt)
	}
	return
}

func getArrSum(arr []int) (sum int) {
	for _, num := range arr {
		sum += num
	}
	return
}

func writeArrSumChan(arr []int, c chan<- int) {
	c <- getArrSum(arr)
}

// 并发求和
func getArrSum2(arr []int) (sum int) {
	// 不需要并发求和
	length := len(arr)
	if length <= 3 {
		sum = getArrSum(arr)
	}

	// 拆分数组
	step := length / 3
	arr1 := arr[:step]
	arr2 := arr[step : step+step]
	arr3 := arr[step+step:]

	// 并发求和
	c := make(chan int)
	go writeArrSumChan(arr1, c)
	go writeArrSumChan(arr2, c)
	go writeArrSumChan(arr3, c)
	v1, v2, v3 := <-c, <-c, <-c
	sum += v1 + v2 + v3

	return
}

func main() {

	var (
		start     = 10
		end       = 110
		length    = 100000000
		arr       = getArr(start, end, length)
		startTime time.Time
		spendTime time.Duration
		sum       int
	)

	// 并发求和
	startTime = time.Now()
	sum = getArrSum2(arr)
	fmt.Println(sum)
	spendTime = time.Since(startTime)
	fmt.Println("并发求和消耗时间:", spendTime)

	// 非并发求和
	startTime = time.Now()
	sum = getArrSum(arr)
	fmt.Println(sum)
	spendTime = time.Since(startTime)
	fmt.Println("非并发求和消耗时间:", spendTime)

	// 主动等待结束
	time.Sleep(time.Second * 3)
}

输出结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html

6450261436
并发求和消耗时间: 25.405516ms
6450261436
非并发求和消耗时间: 47.803627ms
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/30701.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/30701.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定