Ir de un millón de concurrencia nivel en la práctica

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
    Aquí Insertar imagen Descripción

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)
	}
}

Publicado 41 artículos originales · ganado elogios 26 · vistas 8088

Supongo que te gusta

Origin blog.csdn.net/weixin_44879611/article/details/104950858
Recomendado
Clasificación