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
這個是啥意思,后面在群里問了下,瞬間我就明白了,其實通道的通道,還是通道

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM