Goroutine池

goroutine池的应用

  • 本质上是生产者消费者模型
  • 可以有效控制goroutine数量,防止暴涨
  • 需求:
    • 计算一个数字的各个位数之和,例如数字123,结果为1+2+3=6
    • 随机生成数字进行计算
  • 控制台输出结果如下:
job id: 164362 random: 3002688297310473558 result: 81
job id: 164363 random: 8188014692039052954 result: 84
job id: 164364 random: 9199514953162082256 result: 87
job id: 164365 random: 6547609431377245779 result: 96
job id: 164366 random: 5158862497998501304 result: 94
job id: 164367 random: 7591045689235318611 result: 84
job id: 164368 random: 4913457935486468007 result: 93
job id: 164369 random: 6484925446766292271 result: 94
job id: 164370 random: 1630566468428792798 result: 101
job id: 164371 random: 3999715154713986432 result: 96
job id: 164372 random: 8436839935373284876 result: 106
job id: 164373 random: 7590654756672405712 result: 88
job id: 164374 random: 5127823813978664887 result: 103
job id: 164375 random: 5630536624069526117 result: 77
job id: 164376 random: 3445557283367509019 result: 86
job id: 164377 random: 6087330610397339825 result: 83
job id: 164378 random: 3391465925899927215 result: 99

main.go

package main

import (
	"fmt"
	"math/rand"
)

type Job struct {
	Id int
	Random int
}

type Result struct {
	job *Job
	sum int
}

func createGoroutinePool(goNum int, jobChan chan *Job, resultChan chan *Result){
	// 根据goNum开启多个goroutine执行
	for i := 0; i < goNum; i++ {
		go func(jobChan chan *Job, resultChan chan *Result) {
			// 处理每个jobChan中的数据并返回结果
			for job := range jobChan{
				random := job.Random
				var sum int
				// 计算每一位的和
				for random != 0 {
					tmp := random % 10
					sum += tmp
					random /= 10
				}
				// 组织返回结果
				r := &Result{
					job: job,
					sum: sum,
				}
				// 将结果写入通道
				resultChan<- r
			}
		}(jobChan, resultChan)
	}
}

func main() {
	// 工作通道
	jobChan := make(chan *Job, 128)
	// 结果通道
	resultChan := make(chan *Result,128)
	// 创建工作池执行任务
	createGoroutinePool(64, jobChan, resultChan)
	// 打印结果通道数据
	go func(resultChan chan *Result){
		for result := range resultChan{
			fmt.Printf("job id: %v random: %v result: %d\n", result.job.Id, result.job.Random, result.sum)
		}
	}(resultChan)

	var id int
	for {
		id++
		r_num := rand.Int()
		job := &Job{
			Id:     id,
			Random: r_num,
		}
		jobChan<-job
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现一个 goroutine 的一般步骤如下: 1. 定义一个任务队列,用于存储待执行的任务; 2. 定义一个 worker ,用于存储 goroutine; 3. worker 中的 goroutine 从任务队列中获取任务,执行任务; 4. 当任务队列为空时,worker 中的 goroutine 进入休眠状态; 5. 当新任务到达时,唤醒一个休眠的 goroutine,让其执行任务。 下面给出一个可能的实现方案: ```go type Job func() type Pool struct { jobChan chan Job workers []*Worker } type Worker struct { pool *Pool taskChan chan Job } func NewWorker(pool *Pool) *Worker { return &Worker{ pool: pool, taskChan: make(chan Job), } } func (w *Worker) Start() { go func() { for { w.pool.workerChan <- w task := <- w.taskChan task() } }() } func NewPool(numWorkers int) *Pool { pool := &Pool{ jobChan: make(chan Job), workers: make([]*Worker, numWorkers), } for i := 0; i < numWorkers; i++ { worker := NewWorker(pool) pool.workers[i] = worker worker.Start() } go pool.dispatch() return pool } func (p *Pool) dispatch() { for { select { case job := <- p.jobChan: worker := <- p.workerChan worker.taskChan <- job } } } func (p *Pool) AddJob(job Job) { p.jobChan <- job } ``` 以上代码实现了一个 goroutine 的基本功能。在 `NewPool()` 函数中创建了指定数量的 worker,并启动了它们。在 `dispatch()` 函数中,监听了任务队列 `jobChan`,当有新任务到来时,从 worker 中获取一个 worker,将任务分配给它执行。在 `AddJob()` 函数中,向任务队列中添加一个任务。 对于请求量大于消费能力的情况,可以考虑以下几种方案: 1. 增加 worker 数量,提高消费能力; 2. 增加任务队列长度,缓解请求量过大的压力; 3. 采用限流策略,例如令牌桶算法、漏桶算法等,限制请求的速率; 4. 根据负载情况,动态调整 worker 数量,实现自适应扩缩容。 以上方案可以根据实际情况选择合适的方案进行实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值