go协程池实现

1. 什么是协程池

协程池是一种用于管理协程的设计模式,它可以限制并发的协程数量,防止协程泄露,提高程序的性能。通过使用协程池,我们可以更有效地管理和调度协程,避免资源浪费。

2. 为什么需要协程池

在高并发场景下,直接创建大量的协程可能会导致系统资源耗尽,进而影响系统的稳定性。协程池通过预先创建和复用协程,减少了频繁创建和销毁协程的开销,从而提高了系统的性能和稳定性。

3. Go语言中的协程池实现

下面我们将展示如何在Go语言中实现一个简单的动态协程池。

package misc

import (
	"errors"
	"sync"
	"sync/atomic"
	"time"
)
// 任务类型
type Task func()
type GoroutinePool struct {
	TaskQueue     chan Task
	MaxWorker     int32
	MinWorker     int32
	IdleTimeout   time.Duration
	CurrentWorker int32
	WG            sync.WaitGroup
}


// 创建协程池 最小工作协程数 最大工作协程数 空闲超时时间
func NewGoroutinePool(minWorker, maxWorker int32, idleTimeout time.Duration) *GoroutinePool {
	goroutinePool := &GoroutinePool{
		TaskQueue:     make(chan Task, maxWorker),
		MaxWorker:     maxWorker,
		MinWorker:     minWorker,
		IdleTimeout:   idleTimeout,
		CurrentWorker: 0,
	}
	for i := int32(0); i < minWorker; i++ {
		goroutinePool.addWorker()
	}
	return goroutinePool
}

// 添加工作协程
func (gp *GoroutinePool) addWorker() {
	atomic.AddInt32(&gp.CurrentWorker, 1)
	go func() {
		timer := time.NewTimer(gp.IdleTimeout)
		defer atomic.AddInt32(&gp.CurrentWorker, -1)
		defer timer.Stop()
		for {
			select {
			case task, ok := <-gp.TaskQueue:
				if !ok {
					return
				}
				if task != nil {
					task()
					gp.WG.Done()
				}
				timer.Reset(gp.IdleTimeout)
			case <-timer.C:
				if atomic.LoadInt32(&gp.CurrentWorker) > gp.MinWorker {
					return
				}
			}
		}
	}()
}

// 提交任务
func (gp *GoroutinePool) Submit(task Task) error {
	if task == nil {
		return errors.New("task cannot be nil")
	}
	gp.WG.Add(1)
	select {
	case gp.TaskQueue <- task:
	default:
		if atomic.LoadInt32(&gp.CurrentWorker) < gp.MaxWorker {
			gp.addWorker()
		}
		gp.TaskQueue <- task
	}
	return nil
}

// 关闭协程池
func (gp *GoroutinePool) Shutdown() {
	close(gp.TaskQueue)
	gp.WG.Wait()
}


4. 使用示例

下面我们来看一个简单的使用示例,演示如何使用协程池来执行任务。


package main

func main(){
	// 创建协程池
	gp := NewGoroutinePool(10, 1000, 10*time.Second)
	defer gp.Shutdown()
	// 提交任务
	for i := 0; i < 1000; i++ {
		gp.Submit(func() {
			fmt.Println("Hello, World!")
		})
	}
	// 等待任务执行完成
	gp.WG.Wait()
}


5. 总结

通过本文的介绍,我们了解了协程池的概念及其在Go语言中的实现。协程池可以帮助我们更好地管理并发任务,提高系统的性能和稳定性。在实际开发中,合理地使用协程池可以有效地避免资源浪费,提升系统的整体效率。

希望这篇文章对你有所帮助,如果有任何问题或建议,欢迎在评论区留言讨论。

路漫漫其修远兮,吾将上下而求索。
Built with Hugo
主题 StackJimmy 设计