golang 裸写一个pool池控制协程的大小
时间:2022-05-05
本文章向大家介绍golang 裸写一个pool池控制协程的大小,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
http://mp.weixin.qq.com/s?__biz=MjM5OTcxMzE0MQ==&mid=2653369770&idx=1&sn=044be64c577a11a9a13447b373e80082&chksm=bce4d5b08b935ca6ad59abb5cc733a341a5126fefc0e6600bd61c959969c5f77c95fbfb909e3&mpshare=1&scene=1&srcid=1010dpu0DlPHi6y1YmrixifX#rd
就想拿来练手,深入理解了一下,如何控制,协程的大小具体代码如下:
package mainimport ( "fmt"
"strconv"
"time"
"math/rand")//声明成游戏
type Payload struct {
name string
}//打游戏
func (p *Payload) Play() {
fmt.Printf("%s 打LOL游戏...当前任务完成n",p.name)
}//任务
type Job struct {
Payload Payload
}//任务队列
var JobQueue chan Job// 工人
type Worker struct {
name string //工人的名字 // WorkerPool chan JobQueue //对象池
WorkerPool chan chan Job//对象池
JobChannel chan Job //通道里面拿
quit chan bool //}// 新建一个工人
func NewWorker(workerPool chan chan Job,name string) Worker{
fmt.Printf("创建了一个工人,它的名字是:%s n",name); return Worker{
name:name,//工人的名字
WorkerPool: workerPool, //工人在哪个对象池里工作,可以理解成部门
JobChannel:make(chan Job),//工人的任务
quit:make(chan bool),
}
}// 工人开始工作
func (w *Worker) Start(){ //开一个新的协程
go func(){ for{ //注册到对象池中,
w.WorkerPool <-w.JobChannel
fmt.Printf("[%s]把自己注册到 对象池中 n",w.name)
select { //接收到了新的任务
case job :=<- w.JobChannel:
fmt.Printf("[%s] 工人接收到了任务 当前任务的长度是[%d]n",w.name,len(w.WorkerPool))
job.Payload.Play()
time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond) //接收到了任务
case <-w.quit: return
}
}
}()
}
func (w Worker) Stop(){
go func(){
w.quit <- true
}()
}
type Dispatcher struct { //WorkerPool chan JobQueue
name string //调度的名字
maxWorkers int //获取 调试的大小
WorkerPool chan chan Job //注册和工人一样的通道
}
func NewDispatcher(maxWorkers int) *Dispatcher {
pool :=make(chan chan Job,maxWorkers) return &Dispatcher{
WorkerPool:pool,// 将工人放到一个池中,可以理解成一个部门中
name:"调度者",//调度者的名字
maxWorkers:maxWorkers,//这个调度者有好多个工人
}
}
func (d *Dispatcher) Run(){ // 开始运行 for i :=0;i<d.maxWorkers;i++{
worker := NewWorker(d.WorkerPool,fmt.Sprintf("work-%s",strconv.Itoa(i))) //开始工作
worker.Start()
} //监控
go d.dispatch()
}
func (d *Dispatcher) dispatch() { for {
select {
case job :=<-JobQueue:
fmt.Println("调度者,接收到一个工作任务")
time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond) // 调度者接收到一个工作任务
go func (job Job) { //从现有的对象池中拿出一个
jobChannel := <-d.WorkerPool
jobChannel <- job
}(job)
default: //fmt.Println("ok!!")
}
}
}
func initialize() {
maxWorkers := 2;
maxQueue := 4; //初始化一个调试者,并指定它可以操作的 工人个数
dispatch := NewDispatcher(maxWorkers)
JobQueue =make(chan Job,maxQueue) //指定任务的队列长度 //并让它一直接运行
dispatch.Run()
}
func main() { //初始化对象池
initialize() for i:=0;i<10;i++{
p := Payload{
fmt.Sprintf("玩家-[%s]",strconv.Itoa(i)),
}
JobQueue <- Job{
Payload:p,
}
time.Sleep(time.Second)
}
close(JobQueue)
}
其实,他的大概思路就是,好比你在一家公司里,你们ceo(main)给你的领导(dispatcher)分配任务,你的领导(dispatcher)再把任务分配给你(worker),你再去执行具体的任务(playload),我理解了好一会,才明白,上面就是一个模子,可以直接复制就可以用
其中一直不明白
var JobQueue chan chan Job
这个是啥意思,后面在群里问了下,瞬间我就明白了,其实通道的通道,还是通道
- 贪心算法(二)——一般背包问题
- 贪心算法(三)——最佳合并模式
- 贪心算法(四)——最小代价生成树
- 贪心算法(五)——迪杰斯特拉算法
- Tensorflow动态seq2seq使用总结
- 卷积神经网络中PET/CT图像的纹理特征提取
- 深入剖析Spring(四)——AOP
- Java并发编程的艺术(十二)——线程安全
- 用 LSTM 做时间序列预测的一个小例子
- Java并发编程的艺术(十一)——线程池(2)
- Java并发编程的艺术(十)——线程池(1)
- Tensorflow on Spark爬坑指南
- Boost asio 官方教程
- 0基础教你搭建一套可自动化构建的微服务框架(SpringBoot+Dubbo+Docker+Jenkins)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 用了这 7 个 VS Code 插件,想写一辈子代码
- 听说你还不知道Promise的allSettled()和all()的区别?
- React 条件渲染最佳实践(7 种方法)
- 一文带你层层解锁「文件下载」的奥秘
- Android实现简单C/S聊天室应用
- Android仿IOS回弹效果 支持任何控件
- 送你一道字节前端原题(Add sumOf)|文末送红宝书
- xadmin使用formfield_for_dbfield函数过滤下拉表单实例
- Python3之外部文件调用Django程序操作model等文件实现方式
- python 在右键菜单中加入复制目标文件的有效存放路径(单斜杠或者双反斜杠)
- 前端多线程大文件下载实践,提速10倍(拿捏百度云盘)
- docker 中的mysql 经常重启优化
- python MultipartEncoder传输zip文件实例
- 当Flutter遇到节流与防抖的思路和流程优化
- 花样使用Handler与源码分析