golang 裸写一个pool池控制协程的大小
这几天深入的研究了一下golang 的协程,读了一个好文
http://mp.weixin.qq.com/s?__biz=MjM5OTcxMzE0MQ==&mid=2653369770&idx=1&sn=044be64c577a11a9a13447b373e80082&chksm=bce4d5b08b935ca6ad59abb5cc733a341a5126fefc0e6600bd61c959969c5f77c95fbfb909e3&mpshare=1&scene=1&srcid=1010dpu0DlPHi6y1YmrixifX#rd
就想拿来练手,深入理解了一下,如何控制,协程的大小具体代码如下:
package main import (
"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
这个是啥意思,后面在群里问了下,瞬间我就明白了,其实通道的通道,还是通道
golang 裸写一个pool池控制协程的大小的更多相关文章
- 死磕 java线程系列之自己动手写一个线程池
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...
- 手写一个线程池,带你学习ThreadPoolExecutor线程池实现原理
摘要:从手写线程池开始,逐步的分析这些代码在Java的线程池中是如何实现的. 本文分享自华为云社区<手写线程池,对照学习ThreadPoolExecutor线程池实现原理!>,作者:小傅哥 ...
- python-进程池与线程池,协程
一.进程池与线程池 实现并发的手段有两种,多线程和多进程.注:并发是指多个任务看起来是同时运行的.主要是切换+保存状态. 当我们需要执行的并发任务大于cpu的核数时,我们需要知道一个操作系统不能无限的 ...
- 并发编程(六)——进程/线程池、协程、gevent第三方库
进程/线程池.协程.gevent第三方库 一.进程/线程池 1.进程池 (1)什么是进程池 如果需要创建的子进程数量不大,可以直接利用multiprocess中的Process来创建.但是当需要创建上 ...
- 进程池与线程池、协程、协程实现TCP服务端并发、IO模型
进程池与线程池.协程.协程实现TCP服务端并发.IO模型 一.进程池与线程池 1.线程池 ''' 开进程开线程都需要消耗资源,只不过两者比较的情况下线程消耗的资源比较少 在计算机能够承受范围内最大限度 ...
- concurrent.futures进线程池和协程
concurrent.futures 异步执行进程线程池的模块,一个抽象类,定义submit,map,shutdown方法 from concurrent.futures import Process ...
- Python 37 进程池与线程池 、 协程
一:进程池与线程池 提交任务的两种方式: 1.同步调用:提交完一个任务之后,就在原地等待,等任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行 2.异步调用:提交完一个任务之后, ...
- python day 20: 线程池与协程,多进程TCP服务器
目录 python day 20: 线程池与协程 2. 线程 3. 进程 4. 协程:gevent模块,又叫微线程 5. 扩展 6. 自定义线程池 7. 实现多进程TCP服务器 8. 实现多线程TCP ...
- 并发编程 --进、线程池、协程、IO模型
内容目录: 1.socket服务端实现并发 2.进程池,线程池 3.协程 4.IO模型 1.socket服务端实现并发 # 客户端: import socket client = socket.soc ...
随机推荐
- JSON中eval与parse的区别
json的的解析方法 (非原创) json的解析方法共有两种:eval_r() 和 JSON.parse(),使用方法如下: var jsonData = '{"data1":&q ...
- Struts的jar说明
- C语言 插入排序 算法导论chapter2
#include <stdio.h> #define N 10 //INSERTION-SORT int main() { ,,,,,,,,,}; int key; ;j<N;j++ ...
- nginx负载SignalR
前几天写了篇聊天室服务器扩展随想,今天有空开始实施第一步, 聊天服务器用SignalR self-host,负载用nginx,当然这只是测试,实际使用可能还需要修改. 第一步,搭好SignalR服务, ...
- docker容器与容器云读书笔记1
搭建docker应用栈 操作系统: ubuntu 16.04.1 LTS 桌面版 1. 准备工作 换网易源, gedit 会报一个metadata的告警, 不用理会, sudo apt-get upd ...
- 修改组策略,禁止用户修改IP
运行中打开gepdit.msc,依次打开用户配置,管理模板,网络,网络连接:在右侧将“禁止访问LAN链接组建的属性”.“为管理员启用windows2000网络连接设置”设置为已启用即可令用户无法访问网 ...
- 2014 39th ACM-ICPC 北京赛区 总结
万万没想到,拿金了. 在经历了西安赛区的打铁经历,感觉我们已经很坦然了.怎么说呢,虽说有阴影,但那也是成长的一步.我在西安打铁之后跟队友跟姐姐说过“如果北京是铜或者铁,我就退役”.记得曾经,很多人问我 ...
- h5手机页面禁止缩放
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable= ...
- code first提示已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭解决方法
使用codefirst查询当然是必不可少的,但有时不小心可能很简单的查询也会导致异常. 下面用codefirst做个示例简单演示下异常发生的场景: var attendlist = db.Databa ...
- APP里如何添加本地文本
首先考虑到用webview加载,那么久需要把文本转化成html的形势啊:如下,先把文字放到一个文本里,然后 文本转换H5: 1.在word中将文件格式布局 2.word中文本标题设为宋体标题,设字号, ...