Golang WorkerPool线程池并发模式示例详解

 更新时间:2022年08月17日 09:12:32   作者:龚国玮  
这篇文章主要为大家介绍了Golang WorkerPool线程池并发模式示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

 正文

Worker Pools 线程池是一种并发模式。该模式中维护了固定数量的多个工作器,这些工作器等待着管理者分配可并发执行的任务。该模式避免了短时间任务创建和销毁线程的代价。

golang 中,我们使用 goroutinechannel 来构建这种模式。工作器 worker 由一个 goroutine 定义,该 goroutine 通过 channel 获取数据。

处理CVS文件记录

接下来让我们通过一个例子,来进一步理解该模式。假设您需要处理来自 CVS 文件的记录数据,我们需要将该文件中的经纬度保存到数据库中。代码如下。

package main
import (
	"encoding/csv"
	"fmt"
	"os"
	"time"
)
type city struct {
	name     string
	location string
}
func createCity(record city) {
	time.Sleep(10 * time.Millisecond)
}
func main() {
	startTime := time.Now()
	csvFile, err := os.Open("cities.csv")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("Successfully Opened CSV file")
	defer csvFile.Close()
	csvLines, err := csv.NewReader(csvFile).ReadAll()
	if err != nil {
		fmt.Println(err)
	}
	counter := 0
	for _, line := range csvLines {
		counter++
		createCity(city{
			name:     line[0],
			location: line[1],
		})
	}
	fmt.Println("records saved:", counter)
	fmt.Println("total time:", time.Since(startTime))
}

🚚 获取测试数据

cities.csv

输出:

正如我们所看到的,保存 CSV 中所有记录需要 55 秒,这是很长的时间,可能会导致很多性能问题。用户如果想要上传 CSV 文件,那体验感一定很差。

如何解决这个问题?那我们就使用线程池的方法试试看。

线程池耗时差异

在如下示例中,我们将解决相同的需求,但通过线程池,耗时方面,我们能够看到巨大的差异。来吧!

代码如下

package main
import (
	"encoding/csv"
	"fmt"
	"os"
	"time"
)
type city struct {
	name     string
	location string
}
func createCity(record city) {
	time.Sleep(10 * time.Millisecond)
}
func readData(cityChn chan []city) {
	var cities []city
	csvFile, err := os.Open("cities.csv")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("Successfully Opened CSV file")
	defer csvFile.Close()
	csvLines, err := csv.NewReader(csvFile).ReadAll()
	if err != nil {
		fmt.Println(err)
	}
	for _, line := range csvLines {
		cities = append(cities, city{
			name:     line[0],
			location: line[1],
		})
	}
	cityChn <- cities
}
func worker(cityChn chan city) {
	for val := range cityChn {
		createCity(val)
	}
}
func main() {
	startTime := time.Now()
	cities := make(chan []city)
	go readData(cities)
	const workers = 5
	jobs := make(chan city, 1000)
	for w := 1; w <= workers; w++ {
		go worker(jobs)
	}
	counter := 0
	for _, val := range <-cities {
		counter++
		jobs <- val
	}
	fmt.Println("records saved:", counter)
	fmt.Println("total time:", time.Since(startTime))
}

输出:

你看到很大的不同了吗?现在同样的过程只需要 8 秒。正如您所见,当我们需要处理大量数据时,线程池非常有用。

使用线程池,我们必须定义一个函数,在示例中该函数为 worker,该函数用于定义工作进程,您可以看到它接收一个 Channel 通道来处理数据。 另外,我们必须在数据传递到通道之前启动 goroutines 协程,当 Channel 通道获取到值时,goroutines 工作者开始处理它们。

🎉 现在您知道如何实现线程池了!

以上就是Golang WorkerPool线程池并发模式示例详解的详细内容,更多关于Golang WorkerPool线程池并发的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:

相关文章

  • go-kit组件使用hystrix中间件的操作

    go-kit组件使用hystrix中间件的操作

    这篇文章主要介绍了go-kit组件使用hystrix中间件的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Go文件操作(新建打开写入读取删除关闭)学习笔记

    Go文件操作(新建打开写入读取删除关闭)学习笔记

    这篇文章主要为大家介绍了Go文件操作(新建打开写入读取删除关闭)学习笔记,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • 详解Go语言如何使用xorm实现读取mysql

    详解Go语言如何使用xorm实现读取mysql

    xorm是go语言的常用orm之一,可以用来操作数据库。本文就来和大家聊聊Go语言如何使用xorm实现读取mysql功能,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-11-11
  • Go语言Gin处理响应方式详解

    Go语言Gin处理响应方式详解

    gin框架封装了常用的数据格式方法响应于客户端,下面这篇文章主要给大家介绍了关于Go语言Gin处理响应方式的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • golang调试bug及性能监控方式实践总结

    golang调试bug及性能监控方式实践总结

    这篇文章主要为大家介绍了golang调试bug及性能监控方式实践是总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • Go语言中 Channel 详解

    Go语言中 Channel 详解

    Go 语言中的 channel 是实现 goroutine 间无锁通信的关键机制,他使得写多线程并发程序变得简单、灵活、触手可得。下面就个人理解对 channel 使用过程中应该注意的地方进行一个简要的总结。
    2018-10-10
  • 浅析Go中序列化与反序列化的基本使用

    浅析Go中序列化与反序列化的基本使用

    序列化是指将对象转换成字节流,从而存储对象或将对象传输到内存、数据库或文件的过程,反向过程称为“反序列化”。本文主要介绍了Go中序列化与反序列化的基本使用,需要的可以参考一下
    2023-04-04
  • go无缓冲通道的实现及应用

    go无缓冲通道的实现及应用

    在Go语言中,无缓冲通道是一种特殊的通道类型,本文主要介绍了go无缓冲通道的实现及应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-11-11
  • Golang学习笔记之安装Go1.15版本(win/linux/macos/docker安装)

    Golang学习笔记之安装Go1.15版本(win/linux/macos/docker安装)

    这篇文章主要介绍了Golang学习笔记之安装Go1.15版本(win/linux/macos/docker安装),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • go logger不侵入业务代码使用slog替换zap并实现callerSkip详解

    go logger不侵入业务代码使用slog替换zap并实现callerSkip详解

    这篇文章主要为大家介绍了go logger不侵入业务代码使用slog替换zap并实现callerSkip详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09

最新评论