Go实现简单的协程池(通过channel实现)

go编程时,goroutine是非常有用的特性。然而,实践中最好不要无限制的使用goroutine,例如一次性开一万个goroutine去读写文件是很危险的。为了控制goroutine的并行量,有很多框架或库实现了协程池,例如ants(很推荐)。 当小项目不想引入第三方库时,可以借助channel自己实现一个简易的协程池。

首先,创建一个package,不妨名为grpool

package grpool

import "sync"

type GoRoutinePool struct {
	wg       sync.WaitGroup
	poolCh   chan int8        // 用于控制并行数
	resultCh chan interface{} // 子任务结果
}

// NewGoRoutinePool 创建一个协程池,池容量poolSize, 任务数taskCount
func NewGoRoutinePool(poolSize, taskCount int) *GoRoutinePool {
	grPool := &GoRoutinePool{
		wg:       sync.WaitGroup{},
		poolCh:   make(chan int8, poolSize),
		resultCh: make(chan interface{}, taskCount),
	}
	grPool.wg.Add(taskCount)
	return grPool
}

// TaskStart 子任务开始时占用名额
func (g *GoRoutinePool) TaskStart() {
	g.poolCh <- 1 // 占用一个名额
}

// TaskEnd 子任务结束时释放名额,建议在GoRoutine开头使用defer调用
func (g *GoRoutinePool) TaskEnd() {
	<-g.poolCh // 释放一个名额
	g.wg.Done()
}

// AddResult 收集一个任务结果
func (g *GoRoutinePool) AddResult(val interface{}) {
	g.resultCh <- val
}

// Wait 阻塞等待所有子协程执行完成,并返回结果
func (g *GoRoutinePool) Wait() []interface{} {
	g.wg.Wait()
	close(g.resultCh)
	close(g.poolCh)
	results := make([]interface{}, 0, cap(g.resultCh))
	for res := range g.resultCh {
		results = append(results, res)
	}
	return results
}

使用实例:

package main

import (
	"fmt"
	"time"

	"video-composer/common/grpool"
)

func main() {
	grPool := grpool.NewGoRoutinePool(2, 7) // 创建一个协程池
	for i := 0; i < 7; i++ {
		go func(idx int) {
			grPool.TaskStart()     // 子任务开始时
			defer grPool.TaskEnd() // 子任务结束时
			// ================= 子任务 ======================
			fmt.Println("Start ", idx)
			time.Sleep(time.Second)
			fmt.Println("        End ", idx)
			// ==============================================
			grPool.AddResult(idx) // 子任务结果
		}(i)
	}
	results := grPool.Wait() // 等待所有子任务完成,并获取结果
	for _, res := range results {
		fmt.Println("result: ", res)
	}
}

相关推荐

  1. Go实现简单通过channel实现

    2024-04-13 13:46:02       42 阅读
  2. go实现

    2024-04-13 13:46:02       49 阅读
  3. Go 通过 goroutines 实现类似线模式

    2024-04-13 13:46:02       50 阅读
  4. golang 实现

    2024-04-13 13:46:02       64 阅读
  5. 面:go能不能手写一个简单

    2024-04-13 13:46:02       43 阅读
  6. 简单剖析tRPC-Go中使用第三方ants

    2024-04-13 13:46:02       39 阅读
  7. 简易线实现

    2024-04-13 13:46:02       49 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-13 13:46:02       106 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-13 13:46:02       116 阅读
  3. 在Django里面运行非项目文件

    2024-04-13 13:46:02       95 阅读
  4. Python语言-面向对象

    2024-04-13 13:46:02       103 阅读

热门阅读

  1. vLLM部署Qwen1.5-32B-Chat

    2024-04-13 13:46:02       48 阅读
  2. Linux环境下的C/C++开发学习之旅

    2024-04-13 13:46:02       145 阅读
  3. Vue中的.env文件:配置、用法和注意事项

    2024-04-13 13:46:02       42 阅读
  4. linux下c++实现音乐播放软件

    2024-04-13 13:46:02       37 阅读
  5. 统一登陆实现简化流程

    2024-04-13 13:46:02       39 阅读
  6. linux c UDP 应用

    2024-04-13 13:46:02       43 阅读
  7. 作业第二次

    2024-04-13 13:46:02       33 阅读
  8. SpringBoot项目快速打印controller类的URL

    2024-04-13 13:46:02       42 阅读
  9. Nginx-调度器、优化

    2024-04-13 13:46:02       47 阅读