Go并发之百万级处理

代码和注释均在代码:

package main

import (
	"fmt"
	"runtime"
	"time"
)

//---------------------Job-------------------------
type Job interface {
	Do()
}
// 一个数据接口,所有的数据都要实现该接口,才能被传递进来
//实现Job接口的一个数据实例,需要实现一个Do()方法,对数据的处理就在这个Do()方法中。

/*
Job通道:
    这里有两个Job通道:
    1、WorkerPool的Job channel,用于调用者把具体的数据写入到这里,WorkerPool读取。
    2、Worker的Job channel,当WorkerPool读取到Job,并拿到可用的Worker的时候,会将Job实例写入该Worker的Job channel,用来直接执行Do()方法。
*/
//--------------------Worker-----------------------
type Worker struct {
	JobQueue chan Job //Worker的Job通道
}

func NewWorker() Worker {
	return Worker{JobQueue: make(chan Job)}
}
//每一个被初始化的worker都会在后期单独占用一个协程
//初始化的时候会先把自己的JobQueue传递到Worker通道中,
//然后阻塞读取自己的JobQueue,读到一个Job就执行Job对象的Do()方法。

func (w Worker) Run(wq chan chan Job)  {
	go func() {
		for{
			wq <- w.JobQueue
			select {
			case job := <- w.JobQueue:
				job.Do()
			}
		}
	}()
}

//----------------WorkerPool---------------------
//工作池(WorkerPool):
type WorkerPool struct {
	workerlen int 				//WorkerPool中同时 存在Worker的个数
	JobQueue chan Job     		// WorkerPool的Job通道
	WorkerQueue chan chan Job
}
//初始化时会按照传入的num,启动num个后台协程,然后循环读取Job通道里面的数据,
//读到一个数据时,再获取一个可用的Worker,并将Job对象传递到该Worker的chan通道

func NewWorkerPool(workerlen int) *WorkerPool {
	return &WorkerPool{
		workerlen: workerlen,
		JobQueue: make(chan Job),
		WorkerQueue: make(chan chan Job,workerlen),
	}
}

func (wp *WorkerPool) Run()  {
	fmt.Println("初始化worker...")
	for i:=0;i<wp.workerlen;i++ {
		worker := NewWorker()
		worker.Run(wp.WorkerQueue)
	}

	go func() {
		for{
			select {
			case job := <-wp.JobQueue:
				worker :=<-wp.WorkerQueue
				worker <- job
			}
		}
	}()
}

//------------------测试--------------------

type Score struct {
	Num int
}

func (s *Score) Do()  {
	fmt.Println("num:",s.Num)
	time.Sleep(time.Second*1*1)
}

func main() {
	num := 100*100*20
	p := NewWorkerPool(num)
	p.Run()
	datanum := 100*100*100*100
	go func() {
		for i:=1;i<datanum;i++{
			sc := &Score{Num: i}
			p.JobQueue <- sc
		}
	}()

	for{
		fmt.Println("runtime.NumGoroutine():",runtime.NumGoroutine())
		time.Sleep(time.Second*2)
	}
}

  

posted @ 2021-01-25 14:49  pebblecome  阅读(315)  评论(0)    收藏  举报