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