実際に百万レベルの同時実行を行きます

序文

ベースのGolangし、Go言語で複雑な伝統的なOSのプロセスと異なるのスレッドが、同時ユーザーモードに基づいており、この同時やり方は非常に軽量になり、それが簡単に数十並行論理の何千もの実行することができます。

同時実行同時実行モデルの一種が、CSPの実装に属して行き、同時実行モデルのCSPのコアコンセプトは次のとおりです。「DOは、共有メモリを介して通信するが、渡す必要がありません
共有メモリ通信に通じ。」これは、囲碁の言語で達成されゴルーチンとチャンネルです。

スレッドプール

  • ジョブはタスク要求であります
  • ワーカースレッド
  • ワーカープールは、スレッドプールです
    ここに画像を挿入説明

コードの実装

Job.Go

タスクインターフェース

// Job接口 含一个do方法,实现该接口,即为一个请求任务
type Job interface {
	Do()
}

worker.go

スレッド

// 工作线程结构,里面是一个管道,放多个请求任务
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

スレッドプール

// 线程池
// 线程数、任务队列、装任务队列的管道
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

主な機能

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

公開された41元の記事 ウォン称賛26 ビュー8088

おすすめ

転載: blog.csdn.net/weixin_44879611/article/details/104950858