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 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
这个是啥意思,后面在群里问了下,瞬间我就明白了,其实通道的通道,还是通道

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2017-05-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开发与安全

linux网络编程之进程间通信基础(二):死锁、信号量与PV原语简介

一、死锁 (1) 死锁是指多个进程之间相互等待对方的资源,而在得到对方资源之前又不释放自己的资源,这样,造成循环等待的一种现象。如果所有进程都在等待一个不可能发...

2590
来自专栏微信终端开发团队的专栏

iOS微信特殊字符保护方案

一般来说,特殊字符闪退是系统漏洞引起,只要更新系统就行。但大部分用户不愿意更新系统...

84514
来自专栏Java3y

【SSH测试整合Demo】企业人事管理系统

前言 前面我们已经学习了怎么整合SSH框架了。是时候拿一个小项目来练练手了….我们现在要设计一个企业人事管理系统… 需求: **要求对员工信息进行维护; ** ...

43513
来自专栏Golang语言社区

golang 裸写一个pool池控制协程的大小

这几天深入的研究了一下golang 的协程,读了一个好文 http://mp.weixin.qq.com/s?__biz=MjM5OTcxMzE0MQ==&mi...

3916
来自专栏飞雪无情的博客

Android布尔型配置存储优化

在Android开发的过程中,我们基本上都会遇到是否开启自动备份、是否保存账号、是否自动登陆、是否开启向导等这样的选项功能,对于这类功能,我们一般的做法是采用S...

1103
来自专栏互联网技术栈

Netflix Archaius 分布式配置管理依赖构件

archaius是Netflix公司开源项目之一,基于java的配置管理类库,主要用于多配置存储的动态获取。主要功能是对apache common config...

1542
来自专栏Linyb极客之路

并发编程之Semaphore

一、简介 Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。很多年以来,我都觉得从字面上很难理解...

4258
来自专栏武军超python专栏

2018年8月18日初识tkinter

把C盘里面的东西移动到其他盘对文件有影响吗?普通文件如音频视频没有影响,但是如果是软件的话 下载的时候会在注册表中记录打开文件的路径,如果移动到其他盘的话注册...

1242
来自专栏数据之美

修改 mysql/oracle/bash/vimrc/cmd 提示符格式与颜色

(1)修改mysql提示符: MySQL 客户端的默认提示符是 "mysql>",基本上没什么实际作用。其实可以修改这个提示符,让它显示一些有用的信息,例如当前...

26710
来自专栏滕先生的博客

地图相关 CoreLocation框架介绍请求用户授权方法CLLocationManager 属性和方法CLLocation 位置对象介绍三、地理编码的实现

33112

扫码关注云+社区

领取腾讯云代金券