这几天深入的研究了一下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池控制协程的大小的更多相关文章

  1. 死磕 java线程系列之自己动手写一个线程池

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...

  2. 手写一个线程池,带你学习ThreadPoolExecutor线程池实现原理

    摘要:从手写线程池开始,逐步的分析这些代码在Java的线程池中是如何实现的. 本文分享自华为云社区<手写线程池,对照学习ThreadPoolExecutor线程池实现原理!>,作者:小傅哥 ...

  3. python-进程池与线程池,协程

    一.进程池与线程池 实现并发的手段有两种,多线程和多进程.注:并发是指多个任务看起来是同时运行的.主要是切换+保存状态. 当我们需要执行的并发任务大于cpu的核数时,我们需要知道一个操作系统不能无限的 ...

  4. 并发编程(六)——进程/线程池、协程、gevent第三方库

    进程/线程池.协程.gevent第三方库 一.进程/线程池 1.进程池 (1)什么是进程池 如果需要创建的子进程数量不大,可以直接利用multiprocess中的Process来创建.但是当需要创建上 ...

  5. 进程池与线程池、协程、协程实现TCP服务端并发、IO模型

    进程池与线程池.协程.协程实现TCP服务端并发.IO模型 一.进程池与线程池 1.线程池 ''' 开进程开线程都需要消耗资源,只不过两者比较的情况下线程消耗的资源比较少 在计算机能够承受范围内最大限度 ...

  6. concurrent.futures进线程池和协程

    concurrent.futures 异步执行进程线程池的模块,一个抽象类,定义submit,map,shutdown方法 from concurrent.futures import Process ...

  7. Python 37 进程池与线程池 、 协程

    一:进程池与线程池 提交任务的两种方式: 1.同步调用:提交完一个任务之后,就在原地等待,等任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行 2.异步调用:提交完一个任务之后, ...

  8. python day 20: 线程池与协程,多进程TCP服务器

    目录 python day 20: 线程池与协程 2. 线程 3. 进程 4. 协程:gevent模块,又叫微线程 5. 扩展 6. 自定义线程池 7. 实现多进程TCP服务器 8. 实现多线程TCP ...

  9. 并发编程 --进、线程池、协程、IO模型

    内容目录: 1.socket服务端实现并发 2.进程池,线程池 3.协程 4.IO模型 1.socket服务端实现并发 # 客户端: import socket client = socket.soc ...

随机推荐

  1. docker版wordpress

    拉取wordpress镜像 docker pull wordpress:latest 创建mysql 容器docker run --name wordpress-mysql -e MYSQL_ROOT ...

  2. airflow 优化

    1. 页面默认加载数据过多,加载慢. 修改 .../python2.7/site-packages/airflow/www/views.py文件, 1823行, page_size参数, 比如改成18 ...

  3. C#操作Excel文件

    .Net平台上对Excel进行操作主要有两种方式.第一种,把Excel文件看成一个数据库,通过OleDb的方式进行读取与操作:第二种,调用Excel的COM组件.两种方式各有特点. 注意一些简单的问题 ...

  4. Python AES - base64 加解密

    首先python引用AES加密 from Crypto.Cipher import AES 需要先安装  Crypto  模块, 可以使用 easy_install 进行安装   会自动去官网进行搜索 ...

  5. Spring mvc时间格式处理

    spring mvc中,如果时间格式是yyyy-MM-dd,传入后台会报错,要增加一些配置才可以. 1.修改spring-mvc.xml,增加org.springframework.format.su ...

  6. MATLAB曲面插值及交叉验证

    在离散数据的基础上补插连续函数,使得这条连续曲线通过全部给定的离散数据点.插值是离散函数逼近的重要方法,利用它可通过函数在有限个点处的取值状况,估算出函数在其他点处的近似值.曲面插值是对三维数据进行离 ...

  7. sql server 锁

     锁模式 锁模式 说明 共享 (S) 用于不更改或不更新数据的读取操作,如 SELECT 语句. 更新 (U) 用于可更新的资源中. 防止当多个会话在读取.锁定以及随后可能进行的资源更新时发生常见形式 ...

  8. Java并发集合的实现原理

    本文简要介绍Java并发编程方面常用的类和集合,并介绍下其实现原理. AtomicInteger 可以用原子方式更新int值.类 AtomicBoolean.AtomicInteger.AtomicL ...

  9. java的remote shell

    http://www.ganymed.ethz.ch/ssh2/ 此程序的目的是执行远程机器上的Shell脚本. [环境参数] 远程机器IP:172.17.24.212 用户名:root 密码:zhe ...

  10. 分布式消息总线,基于.NET Socket Tcp的发布-订阅框架之离线支持,附代码下载

    一.分布式消息总线以及基于Socket的实现 在前面的分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载一文之中给大家分享和介绍了一个极其简单也非常容易上的基于.N ...