Golang高并发工作池

本文介绍了一种在Go语言中实现高效并发处理的方法——工作池。通过限制协程数量,避免了因groutine过度创建而导致的性能下降。文章详细解释了工作池的原理,提供了完整的代码示例,包括如何定义任务接口、实现工作结构体、创建和管理工作者及任务发送者,以及如何初始化和运行工作池。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

go程序开发过程中,通过简单的调用go func 函数来开启协程,容易导致程序死锁,并且会无限制的开启groutine,groutine数量激增的情况下并发性能会明显下降,所以需要考虑使用工作池来控制协程数量,以达到高并发的效果.
直接上代码(JobPool.go)

package utils

import (
    "fmt"
)

// 定义任务接口,所有实现该接口的均实现工作池
type Task interface {
    DoTask() error
}

// 定义工作结构体
type Job struct {
    Task Task
}

// 定义全部的工作队列
var JobQueue chan Job

// 定义工作者
type Worker struct {
    WorkerPool chan chan Job    // 工人对象池
    JobChannel  chan Job        // 管道里面拿Job
    quit chan bool
}

// 新建一个工作者
func NewWorker(workerPool chan chan Job) Worker {
    return Worker{
        WorkerPool: workerPool, // 工人对象池
        JobChannel: make(chan Job), //工人的任务
        quit:       make(chan bool),
    }
}

// 工作池启动主函数
func(w *Worker)Start(){
    // 开一个新的协程
    go func() {
        for{
            // 注册任务到工作池
            w.WorkerPool <- w.JobChannel
            select {
            // 接收到任务
            case job := <- w.JobChannel:
                // 执行任务
                err := job.Task.DoTask()
                if err != nil {
                    fmt.Println("任务执行失败")
                }
            // 接收退出的任务, 停止任务
            case <- w.quit:
                return
            }
        }
    }()
}

// 退出执行工作
func (w *Worker) Stop(){
    go func(){
        w.quit <- true
    }()
}

// 定义任务发送者
type Sender struct {
    maxWorkers int  // 最大工人数
    WorkerPool chan chan Job    // 注册工作通道
    quit chan bool  // 退出信号
}

// 注册新发送者
func NewSender(maxWorkers int) *Sender{
    Pool := make(chan chan Job, maxWorkers)
    return &Sender{
        WorkerPool: Pool,       // 将工作者放到一个工作池中
        maxWorkers: maxWorkers, // 最大工作者数量
        quit: make(chan bool),
    }
}

// 工作分发器
func(s *Sender)Run(){
    for i:=0; i<s.maxWorkers; i++{
        worker := NewWorker(s.WorkerPool)
        // 执行任务
        worker.Start()
    }
    // 监控任务发送
    go s.Send()
}

// 退出发放工作
func (s *Sender) Quit(){
    go func(){
        s.quit <- true
    }()
}

func(s *Sender)Send(){
    for {
        select {
        // 接收到任务
        case job :=<- JobQueue:
            go func(job Job) {
                jobChan := <- s.WorkerPool
                jobChan <- job
            }(job)
        // 退出任务分发
        case <- s.quit:
            return
        }
    }
}

// 初始化对象池
func InitPool()  {
    maxWorkers := 4
    maxQueue := 20
    // 初始化一个任务发送者,指定工作者数量
    send := NewSender(maxWorkers)
        // 指定任务的队列长度
    JobQueue = make(chan Job,maxQueue) 
    // 一直运行任务发送
    send.Run()
}

使用方法

package main

import (
    "fmt"
    "os"
    "test/utils"    //引用: JobPool是放在test项目的utils包下
    "time"
)

type Test struct {
    num int
}

//  任务,实现JobPool的Task接口
func(t *Test)DoTask() error{
    f, err := os.OpenFile("log.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
    if err != nil {
        return err
    }
    defer f.Close()
    f.WriteString(fmt.Sprintf("这是任务:%d号,执行时间为:%s \n", t.num, fmt.Sprintf("%s", time.Now())))
    return nil
}

func main(){
    // 初始化对象池
    utils.InitPool()
    for i:=1;i<40 ;i++{
        // 注册任务到Job队列中
        task := &Test{i}
        utils.JobQueue <- utils.Job{
            Task:task,
        }
    }
    // time.Sleep(180 * time.Second)
    // 执行结束,关闭管道
    close(utils.JobQueue)
}

参考文章: http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang/

Go语言(golang)因其轻量级、高效和内置支持并发的特点,非常适合用于构建高并发服务器。以下几点描述了为何Go适合高并发场景以及如何实现: 1. ** goroutines 和 channels**:Go的核心特性之一就是goroutine和channel。goroutine是一种轻量级线程,创建成本低,可以同时处理大量请求,而channel则提供了一种安全的异步通信机制,使得并发任务间的数据传递变得简单。 2. ** CSP (Communicating Sequential Processes)**:Go的设计理念深受 Communicating Sequential Processes (CSP) 影响,鼓励程序员编写独立运行并能相互协作的小型函数式程序,这有助于组织和管理复杂的并发逻辑。 3. **内存模型**:Go的内存模型是基于单线程的,但在用户空间内通过goroutines模拟并发,这种设计避免了锁的竞争,提高了性能。 4. **惰性计算和短暂停留**:对于网络I/O密集型应用,Go的net/http包利用HTTP连接复用和长生命周期的连接池,减少了不必要的上下文切换。 5. **并发安全库**:Go的标准库提供了如sync.Map这样的并发安全数据结构,帮助开发者在高并发环境中操作共享数据。 要创建一个高并发服务器,你可以按照以下步骤: - 使用`net/http`包创建Server实例。 - 实现HandlerFunc来处理请求。 - 如果有需要,使用context包进行请求超时控制和取消。 - 利用goroutines和channels处理并发请求。 ```go package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { // 处理请求逻辑... fmt.Fprintln(w, "Hello from Go!") } func main() { http.HandleFunc("/", handler) err := http.ListenAndServe(":8080", nil) if err != nil { panic(err) } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值