Go 通过 goroutines 实现类似线程池的模式

Go 语言自身不提供传统意义上的线程池(thread pool)概念,因为它有一套自己的并发模型,基于 goroutines 和 channels。goroutine 是 Go 语言的轻量级线程,调度由 Go 运行时管理,不需要像操作系统线程那样显式创建和管理线程池。

goroutines 在多核处理器上可以并行运行,Go 运行时会自动在可用的逻辑核心之间分配 goroutines。这意味着通常不需要自己管理一个线程池;只需启动所需数量的 goroutines,剩下的工作交给 Go 的调度器来处理。

如果需要限制同时运行的任务数量,或者想要复用一定数量的工作单元以减少创建和销毁 goroutines 的开销,可以实现一个类似线程池的模式。一个简单的方式是使用 buffered channel 来限制并发。

下面是一个实现了固定数量工作者的 goroutines 池的简单例子:

go 复制代码
package main

import (
	"fmt"
	"sync"
	"time"
)

func worker(tasksCh <-chan int, wg *sync.WaitGroup) {
	defer wg.Done()
	for task := range tasksCh {
		process(task)
	}
}

func process(task int) {
	fmt.Printf("处理任务 %d\n", task)
	time.Sleep(time.Second) // 模拟任务处理时间
}

func main() {
	tasks := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // 任务列表
	nWorkers := 3 // 工作者数量(类似线程池大小)

	tasksCh := make(chan int, len(tasks))
	wg := sync.WaitGroup{}

	// 启动指定数量的工作者 goroutines
	for i := 0; i < nWorkers; i++ {
		wg.Add(1)
		go worker(tasksCh, &wg)
	}

	// 将任务发送到任务通道
	for _, task := range tasks {
		tasksCh <- task
	}
	close(tasksCh) // 发送完毕后关闭通道

	// 等待所有工作者完成
	wg.Wait()
}

其中worker 函数是每个工作者 goroutine 执行的函数,它从 tasksCh 中接收任务。main 函数创建了一个有限大小的任务通道(buffered channel),并启动了固定数量的工作者 goroutines。然后它将所有任务发送到通道中,工作者会并发地处理这些任务,但同时运行的工作者数量不会超过 nWorkers。这样,就可以控制并发执行的任务数量,从而实现类似线程池的行为。

相关推荐
Ruiery6 小时前
Linux 6.6内核 CPU 深度解析(七):调度器启动 — 从单核到多核,调度器分阶段点亮
linux·运维·服务器
50万马克的面包6 小时前
CSDN-栈队列数组-知识点整理
linux·运维·服务器
福兮说8 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理9 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
91刘仁德9 小时前
HTTP协议详解:从URL到HTTP服务器的完整实战
服务器·网络·笔记·网络协议·http
小呆呆6669 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
Dovis(誓平步青云)9 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan10 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_11 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒11 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端