Go协程池设计思路(Task-Job-Worker)

2023-05-16

1. 铺垫:Go 的接收器Receiver

在go语言中,没有类的概念,但是可以给类型(结构体,自定义类型)定义方法。所谓方法就是定义了接受者的函数。接受者定义在func关键字和函数名之间。可以理解成为结构体定义函数方法,类似于C++中的类方法。

type Person struct {
    name string
    age int
}

func (p Person) say() {
    fmt.Printf("I'm %s,%d years old\n",p.name,p.age)
}

接受者类型可以是struct,也可以是指向struc的指针。

  • 接收者的类型为struct
package main

import "fmt"

type Person struct {
name string
age int
}
func (p Person) say() {
fmt.Printf("I'm %s,%d years old\n",p.name,p.age)
}
func (p Person) older(){
    p.age = p.age +1
}
func main() {
    var p1 Person = Person{"lineshen",25}
    p1.older()
    p1.say()
    var p2 *Person = &Person{"leleyue",22}
    p2.older()
    p2.say()
}

output:

I'm lineshen,25 years old
I'm leleyue,22 years old

对于p1的调用,是没有问题的,因为传递的是结构体,在方法中改变结构体属性,并不能改变原来内存中的值。

对于p2的调用会产生疑问,p2明明是个指针,为什么再调用了older方法之后,打印结果还是22 years old?
方法的接受者是Person而调用者是*Person。其实在p2调用时存在一个转换p2.older() -> *p2.older(); p2.say() -> *p2.say()
p2是指向Person实例的指针。因此,方法执行时的接受者实际上还是一个值而非引用,因此值是不会发生改变的。

  • 接收者的类型为指针
package main

import "fmt"

type Person struct {
name string
age int
}
func (p *Person) say() {
fmt.Printf("I'm %s,%d years old\n",p.name,p.age)
}
func (p *Person) older(){
    p.age = p.age +1
}
func main() {
    var p1 Person = Person{"lineshen",25}
    p1.older()
    p1.say()
    var p2 *Person = &Person{"leleyue",22}
    p2.older()
    p2.say()
}

output:

I'm lineshen,26 years old
I'm leleyue,23 years old

此时传递的是引用,并非值。因此,结构体在内存中属性值会跟随函数方法发生相应的改变。

2. 正题:协程池的设计思路

类似于淘宝电商,可能每分钟有百万级别的请求,最简单直观的方法是来一个请求,new goroutine处理这个请求;那么需要的goroutine也是百万级别的。这样做业务处理逻辑是清楚了,但是会导致CPU做很多无用功,因为CPU需要在不同的goroutin之间流转。所以,在实际业务中,应该限制gorotine的个数(一般协程的数量与CPU的数量保持一致,加大CPU的利用率)。一个可行的架构设计如下:

示例代码如下:

package main
import ("fmt"
		"time")

// 任务的属性应该是一个业务函数
type Task struct {
	f func() error // 函数名f, 无参,返回值为error
}

// 创建Task任务
func NewTask(arg_f func() error) *Task {
	task := Task{
		f: arg_f,
	}
	return &task
}

// Task绑定业务方法
func (task *Task) Execute() {
	task.f() // 调用任务中已经绑定好的业务方法
}

// ------------------------------------------------
type Pool struct {
	EntryChannel chan *Task  // 对外的Task入口
	JobsChannel  chan *Task  // 内部的Task队列
	workerNum    int         // 协程池中最大的woker数量
}

// 创建Pool
func NewPool(cap int) *Pool {
	pool := Pool {
	EntryChannel : make(chan *Task),
	JobsChannel  : make(chan *Task),
	workerNum : cap,
	}
	return &pool
}

// Pool绑定干活的方法
func (pool *Pool) worker(workID int) {
	// worker工作 : 永久从JobsChannel取任务 然后执行任务
	for task := range pool.JobsChannel {
		task.Execute()
		fmt.Println("work ID ", workID, " has executed")
	}
}

// Pool绑定协程池工作方法
func (pool *Pool) run() {
	// 定义worker数量
	for i:=0; i<pool.workerNum; i++ {
		go pool.worker(i)
	}
	
	// 从EntryChannel去任务,发送给JobsChannel
	for task := range pool.EntryChannel {
		pool.JobsChannel <- task // 添加task优先级排序逻辑
	}
}

// ------------------------------------------------
func main() {
	// 创建一些任务
	task := NewTask( func() error { // 匿名函数
		fmt.Println(time.Now())
		return nil
	})
	
	// 创建协程池
	pool := NewPool(4)
	
	// 创建多任务,抛给协程池 
	go func() { // 开启新的协程,防止阻塞
		for{
			pool.EntryChannel <- task
		}
	}()
	
	// 启动协程池
	pool.run()
}

output:

work ID  0  has executed
2020-04-13 00:15:28.6042081 +0800 CST m=+0.040858901
work ID  0  has executed
2020-04-13 00:15:28.605204 +0800 CST m=+0.041854801
work ID  0  has executed
2020-04-13 00:15:28.6062025 +0800 CST m=+0.042853301
work ID  0  has executed
2020-04-13 00:15:28.6062025 +0800 CST m=+0.042853301
work ID  0  has executed
2020-04-13 00:15:28.6071987 +0800 CST m=+0.043849501
work ID  0  has executed
2020-04-13 00:15:28.6071987 +0800 CST m=+0.043849501
work ID  0  has executed
2020-04-13 00:15:28.6081959 +0800 CST m=+0.044846701
work ID  0  has executed
2020-04-13 00:15:28.6081959 +0800 CST m=+0.044846701
work ID  0  has executed
2020-04-13 00:15:28.6091933 +0800 CST m=+0.045844101
work ID  0  has executed
2020-04-13 00:15:28.6091933 +0800 CST m=+0.045844101
work ID  0  has executed
2020-04-13 00:15:28.6101907 +0800 CST m=+0.046841501
work ID  0  has executed
2020-04-13 00:15:28.6101907 +0800 CST m=+0.046841501
work ID  0  has executed
2020-04-13 00:15:28.6101907 +0800 CST m=+0.046841501
work ID  0  has executed
2020-04-13 00:15:28.6111882 +0800 CST m=+0.047839001
work ID  0  has executed
2020-04-13 00:15:28.5683041 +0800 CST m=+0.004954901
work ID  1  has executed
2020-04-13 00:15:28.5673053 +0800 CST m=+0.003956101
work ID  3  has executed
2020-04-13 00:15:28.6121853 +0800 CST m=+0.048836101
work ID  3  has executed
2020-04-13 00:15:28.6121853 +0800 CST m=+0.048836101
work ID  3  has executed
2020-04-13 00:15:28.6121853 +0800 CST m=+0.048836101
work ID  3  has executed
2020-04-13 00:15:28.5673053 +0800 CST m=+0.003956101
work ID  2  has executed
2020-04-13 00:15:28.6151779 +0800 CST m=+0.051828701
work ID  2  has executed
2020-04-13 00:15:28.6151779 +0800 CST m=+0.051828701
work ID  2  has executed
2020-04-13 00:15:28.6161747 +0800 CST m=+0.052825501
work ID  2  has executed
2020-04-13 00:15:28.6161747 +0800 CST m=+0.052825501
work ID  2  has executed
2020-04-13 00:15:28.6171731 +0800 CST m=+0.053823901
work ID  2  has executed
2020-04-13 00:15:28.6171731 +0800 CST m=+0.053823901
work ID  2  has executed
2020-04-13 00:15:28.6181705 +0800 CST m=+0.054821301
work ID  2  has executed
2020-04-13 00:15:28.6181705 +0800 CST m=+0.054821301
work ID  2  has executed
2020-04-13 00:15:28.6181705 +0800 CST m=+0.054821301
work ID  2  has executed
2020-04-13 00:15:28.6181705 +0800 CST m=+0.054821301
work ID  2  has executed
2020-04-13 00:15:28.6191668 +0800 CST m=+0.055817601
work ID  2  has executed
2020-04-13 00:15:28.6191668 +0800 CST m=+0.055817601
work ID  2  has executed
2020-04-13 00:15:28.6191668 +0800 CST m=+0.055817601
work ID  2  has executed
2020-04-13 00:15:28.6191668 +0800 CST m=+0.055817601
work ID  2  has executed
2020-04-13 00:15:28.6201639 +0800 CST m=+0.056814701
work ID  2  has executed
2020-04-13 00:15:28.6111882 +0800 CST m=+0.047839001
work ID  0  has executed
2020-04-13 00:15:28.6201639 +0800 CST m=+0.056814701
work ID  0  has executed
2020-04-13 00:15:28.6211612 +0800 CST m=+0.057812001
work ID  0  has executed
2020-04-13 00:15:28.6201639 +0800 CST m=+0.056814701
work ID  2  has executed
2020-04-13 00:15:28.6221586 +0800 CST m=+0.058809401
work ID  2  has executed
2020-04-13 00:15:28.6221586 +0800 CST m=+0.058809401
work ID  2  has executed
2020-04-13 00:15:28.6251574 +0800 CST m=+0.061808201
work ID  2  has executed
2020-04-13 00:15:28.6261523 +0800 CST m=+0.062803101
work ID  2  has executed
2020-04-13 00:15:28.6261523 +0800 CST m=+0.062803101
work ID  2  has executed
2020-04-13 00:15:28.6271454 +0800 CST m=+0.063796201
work ID  2  has executed
2020-04-13 00:15:28.6271454 +0800 CST m=+0.063796201
work ID  2  has executed
2020-04-13 00:15:28.6281435 +0800 CST m=+0.064794301
work ID  2  has executed
2020-04-13 00:15:28.6281435 +0800 CST m=+0.064794301
work ID  2  has executed
2020-04-13 00:15:28.6291399 +0800 CST m=+0.065790701
work ID  2  has executed
2020-04-13 00:15:28.6291399 +0800 CST m=+0.065790701
work ID  2  has executed
2020-04-13 00:15:28.6301372 +0800 CST m=+0.066788001
work ID  2  has executed
2020-04-13 00:15:28.6301372 +0800 CST m=+0.066788001
work ID  2  has executed
2020-04-13 00:15:28.6142098 +0800 CST m=+0.050860601
work ID  3  has executed
2020-04-13 00:15:28.6311355 +0800 CST m=+0.067786301
work ID  3  has executed
2020-04-13 00:15:28.6321319 +0800 CST m=+0.068782701
work ID  3  has executed
2020-04-13 00:15:28.6321319 +0800 CST m=+0.068782701
work ID  3  has executed
2020-04-13 00:15:28.6331302 +0800 CST m=+0.069781001
work ID  3  has executed
2020-04-13 00:15:28.6331302 +0800 CST m=+0.069781001
work ID  3  has executed
2020-04-13 00:15:28.6331302 +0800 CST m=+0.069781001
work ID  3  has executed
2020-04-13 00:15:28.6391157 +0800 CST m=+0.075766501
work ID  3  has executed

学习视频:https://www.bilibili.com/video/BV1cx41197j5?from=search&seid=15155039435359774234

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go协程池设计思路(Task-Job-Worker) 的相关文章

随机推荐

  • IMU校正以及姿态融合

    本文为博主 声时刻 原创文章 xff0c 未经博主允许不得转载 联系方式 xff1a shenshikexmu 64 163 com 缘起 有缘在简极科技兼职两年 接触了IMU xff0c 我去的时候那家公司还是一个要把IMU放进足球的公司
  • socket can 编程

    Socket can 文档原名称 can txt 位于 linux 3 2 0 m3352 Documentation networking can txt CAN 控制器局域网络协议族之 Readme 文件 aka Socket CAN
  • HiEV洞察 | 特斯拉HW4.0再爆猛料,高精定位、雷达均有变动

    作者 查理斯 编辑 王博 特斯拉 HW4 0 消息传出后 xff0c 有人爆料说在硬件层面发生了巨大变化 xff0c 引发行业轰动 大家都在猜测HW4 0 具体做了哪些改动 2月16日 xff0c Twitter用户greentheonly
  • VRPN介绍及使用

    VRPN 介绍及使用 VRPN 简介 Virtual Reality Peripheral Network xff08 VRPN xff09 由一系列的类库组成 xff0c 它也提供一系列的服务在虚拟现实系统中实现应用程序与外围物理设备 x
  • 基于bert模型的文本分类研究:“Predict the Happiness”挑战

    1 前言 在2018年10月 xff0c Google发布了新的语言表示模型BERT Bidirectional Encoder Representations from Transformers 根据他们的论文所言 xff0c 在文本分类
  • Bert演变总结

  • Tof,结构光,三角测距,RGBD,双目,激光雷达,毫米波雷达一文总结(一)

    Tof xff0c 结构光 xff0c 三角测距 xff0c RGBD xff0c 双目 xff0c 激光雷达 xff0c 毫米波雷达一文总结 距离测量算法解析TOF 飞行时间测距法超声波毫米波雷达激光雷达 最近在做一些无人车相关的工作 x
  • OCR-PIL.Image与Base64 String的互相转换

    1 基本环境 py2 python2 7 13py3 python3 6 2PIL pip 2 3 install pillow PIL库已不再维护 xff0c 而pillow是PIL的一个分支 xff0c 如今已超越PIL 2 Conve
  • Java中恒等条件判断:“equals”和“==”

    1 起因 xff1a 字符串恒等判断 String is reference type String str1 61 new String 34 hello 34 String str2 61 new String 34 hello 34
  • SQL小结

    1 SQL模糊查询 like 效率低 xff0c 容易全盘扫描 查找Name中包含字符 39 M 39 的数据 select ename from table where ename like 39 M 39 查找Name中第二个字母为 3
  • golang中的flag模块小结

    1 flag常用函数 无论是c语言还是golang语言或是其他语言 xff0c 启动应用程序时都可以带一些参数 xff0c 然后系统根据传入的参数进行特点的工作 如 xff1a main mode online model bert ch
  • Redis批量操作详解及性能分析

    通过mget批量执行指令可以节约网络连接和数据传输开销 xff0c 在高并发场景下可以节约大量系统资源 本文中 xff0c 我们更进一步 xff0c 比较一下redis提供的几种批量执行指令的性能 1 为什么需要批量执行redis指令 众所
  • NDCG:推荐系统/搜索评价指标

    本文转载自 胖喵 博主 xff0c 详细请看https www cnblogs com by dream p 9403984 html 1 CG xff1a 累计增益 CG xff0c cumulative gain xff0c 只考虑到了
  • 特征共线性问题

    多重共线性是使用线性回归算法时经常要面对的一个问题 在其他算法中 xff0c 例如决策树或者朴素贝叶斯 xff0c 前者的建模过程时逐渐递进 xff0c 每次都只有一个变量参与 xff0c 这种机制含有抗多重共线性干扰的功能 xff1b 后
  • 常见回归和分类损失函数比较

    文章转自知乎作者wdmad xff0c 更多内容建议阅读原文 xff1a https zhuanlan zhihu com p 36431289 本博文属于阅读笔记 xff0c 融合了个人观点 1 损失函数 损失函数的一般表示为 L y f
  • 获取keras中间层输出、模型保存与加载

    1 获取keras中间层输出 model summary and plot import keras from keras models import Model from keras utils import plot model Doc
  • HashMap底层实现和原理

    本文是在阅读知乎老刘作品后的整理 内容基于JDK1 7进行分析 xff0c 1 8做的改动文章末尾进行讲解 1 基本要义 1 1 概述 Hashmap在Map派生中的位置 HashMap基于Map接口实现 xff0c 元素以键值对的方式存储
  • 大疆激光雷达Livox Avia开箱及测试

    大疆激光雷达Livox Avia 箱子 从左至右为 xff1a 大疆激光雷达Livox Avia xff0c 电源转接插座 xff0c 内六角形L型扳手 xff0c 镜头清洁布 xff0c 螺钉包 xff0c 说明书 xff0c 1 5米航
  • Go协程与协程池

    1 Golang协程 golang和其它语言最大区别莫过于goroutine xff0c 也就是go的协程 xff0c example如下 xff1a package main import 34 fmt 34 import 34 time
  • Go协程池设计思路(Task-Job-Worker)

    1 铺垫 xff1a Go 的接收器Receiver 在go语言中 xff0c 没有类的概念 xff0c 但是可以给类型 xff08 结构体 xff0c 自定义类型 xff09 定义方法 所谓方法就是定义了接受者的函数 接受者定义在func