Golang实现协程池
2023-02-18 16:32:40 时间
通过无缓冲的通道实现Worker池,无缓冲的通道好处是:1. 任务不会丢失,所有投递的任务都一定会被处理,如果协程池里的协程都在忙碌中的话,那么会阻塞在往通道投递任务的那一行代码。2. 调用者可以及时的知道协程池是否处于忙碌的状态中。
以下是Work包中的代码:
package work
import "sync"
// work包的目的是展示如何使用无缓冲的通道来创建一个goroutine池, 这些goroutine执行并控制一组工作
// 让其并发工作。在这种情况下, 使用无缓冲的通道要比随意指定一个缓冲区大小的有缓冲的通道好,
// 因为这种情况既不需要一个工作队列,也不需要一组goroutine配合执行。
// 无缓冲的通道保证两个goroutine之间的数据交换。这种使用无缓冲的通道的方法允许调用者知道
// 什么时候goroutine池正在执行工作, 而且如果池中的所有goroutine都在忙,也可以及时通过通道通知调用者。
// 使用无缓冲的通道不会有工作在队列中丢失或者卡住,所有工作都会被处理。
// Worker必须满足接口类型
// 才能使用工作池
type Worker interface {
Task()
}
// Pool提供一个goroutine池, 这个池可以完成任何已提交的Worker任务
type Pool struct {
work chan Worker
wg sync.WaitGroup
}
// New创建一个新协程池
func New(maxGoroutines int) *Pool {
p := Pool{
work: make(chan Worker),
}
p.wg.Add(maxGoroutines)
for i := 0; i < maxGoroutines; i++ {
go func() {
// p.work关闭的时候将该协程从waitgroup中关闭
defer p.wg.Done()
for w := range p.work {
// 阻塞等待执行任务
w.Task()
}
}()
}
return &p
}
// Run提交工作到协程池
func (p *Pool) Run(w Worker) {
p.work <- w
}
// Shutdown 等待所有goroutine停止工作
func (p *Pool) Shutdown() {
close(p.work)
p.wg.Wait()
}
让我们一起通过main包中的代码来看看如何使用协程池:
package main
import (
"GoPratice/work"
"log"
"sync"
"time"
)
// 通过main.go调用work包中的协程池
// 这个示例程序展示如何使用work包
// 创建一个goroutine池并完成工作
// names 提供一组用来显示的名字
var names = []string{
"steve",
"bob",
"mary",
"therese",
"jason",
}
// namePrinter 使用特定方式打印名字
type namePrinter struct {
name string
}
// Task实现Worker接口
func (m *namePrinter) Task() {
log.Println(m.name)
time.Sleep(time.Second)
}
func init() {
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
}
func main() {
// 使用两个goroutine来创建协程池
p := work.New(2)
var wg sync.WaitGroup
wg.Add(100 * len(names))
for i := 0; i < 100; i++ {
// 迭代names切片
for _, name := range names {
// 创建一个namePrinter并提供
// 指定的名字
np := namePrinter{
name: name,
}
go func() {
p.Run(&np)
wg.Done()
}()
}
}
wg.Wait()
// 让工作池停止工作, 等待所有的工作完成
p.Shutdown()
}
相关文章
- [git] git清理远端已删除分支在本地的备份
- [git] Git Clean 清除 untrack 没有加入版本库的文件
- [linux] ab压测工具进行post压力测试
- [Go]golang中的urlencode和urldecode
- [linux] du查找数据大的目录
- [Go] golang获取程序执行的绝对路径
- [linux] 查看centos或ubuntu的系统版本
- [linux] centos系统yum安装rz与sz
- [GO]golang实现AES加解密
- [GO] 解决:crypto/aes: invalid key size 14
- [git] git拉取远程分支代码
- [gitlab] 解决:remote: Ask a project Owner or Maintainer to create a default branch:
- [linux]查看文件目录是否为硬链接
- [go] 解决:concurrent write to websocket connection
- [git] log中Merge branch 'master' of xxx的产生原因
- [Linux] nacos配置中心curl发布和获取服务以及配置
- [linux] Windows 10 家庭版安装wsl ubuntu子系统
- [GIT] git打标签tag和分支branch的区别
- [linux] 使用curl排查接口问题
- [linux] 查看所有的系统用户