prefacio
Golang basado procesos y sistemas operativos tradicionales e hilos de diferente, complicados por el lenguaje Go se basa en el modo de usuario concurrente, de esta manera simultánea se vuelve muy ligero, fácilmente se puede ejecutar a decenas de miles de lógica concurrente.
Ir un tipo de modelo de concurrencia de concurrencia pertenece a la implementación de CSP, el concepto básico de modelo de concurrencia CSP es: "no se comunican a través de memoria compartida, pero debe pasar
a través de la comunicación de memoria compartida." Esto se logra en el idioma Go es goroutine y el canal.
subprocesos
- trabajo es una solicitud de tarea
- un subproceso de trabajo
- Piscina trabajador es un grupo de subprocesos
la implementación del código
Job.Go
interfaz de tarea
// Job接口 含一个do方法,实现该接口,即为一个请求任务
type Job interface {
Do()
}
worker.go
hilo
// 工作线程结构,里面是一个管道,放多个请求任务
type Worker struct {
JobQueue chan Job
}
// 类似构造函数,返回一个工作线程
func NewWorker() Worker {
return Worker{JobQueue: make(chan Job)}
}
// 工作线程的成员函数,处理请求
// 形参wq是一个工作队列
// 调用之后,会起一个线程,无限循环,取出任务,放到线程池中 ???
func (w Worker) Run(wq chan chan Job) {
go func() {
for {
wq <- w.JobQueue
select {
case job := <-w.JobQueue:
job.Do()
}
}
}()
}
workerpool.go
subprocesos
// 线程池
// 线程数、任务队列、装任务队列的管道
type WorkerPool struct {
workerlen int
JobQueue chan Job
WorkerQueue chan chan Job
}
// 线程池的构造函数
func NewWorkerPool(workerlen int) *WorkerPool {
return &WorkerPool{
workerlen: workerlen,
JobQueue: make(chan Job),
WorkerQueue: make(chan chan Job, workerlen),
}
}
// 线程池的成员函数
// 先打印初始化
// 根据工人池的长度,循环构造n个工作线程,然后调用工作线程的Run函数,即:把任务放到线程池中,然后处理这个线程的任务请求
// 开一个协程,一直循环,任务队列中取出任务,如果有,则看工作队列是否有空余线程,如果有,则工作队列中,取出一个工作协程,处理job请求
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 // 处理任务
}
}
}()
}
main.go
La función principal
package main
import (
"fmt"
"runtime"
"time"
)
// 分数结构——打印显示用
type Score struct {
Num int
}
// 分数结构实现了Job接口————即打印自己 然后睡眠2s,即有一个score的请求任务,需要打印自己
func (s *Score) Do() {
fmt.Println("num:", s.Num)
time.Sleep(time.Second)
}
func main() {
//num := 100 * 100 * 20
num := 1
// debug.SetMaxThreads(1000) //设置最⼤大线程数
// 注册⼯工作池,传⼊入任务
// 参数1 worker并发个数
// 长度为20w的工作池
p := NewWorkerPool(num)
// 先运行 挂起
p.Run()
// 创建一亿个分数对象,然后丢进工作池的管道
//datanum := 100 * 100 * 100 * 100
datanum := 1
go func() {
for i := 1; i <= datanum; i++ {
sc := &Score{Num: i}
p.JobQueue <- sc
}
}()
// 每隔2秒打印目前的协程数
for {
fmt.Println("runtime.NumGoroutine() :", runtime.NumGoroutine())
time.Sleep(2 * time.Second)
}
}