go实现协程池
参考解析
**题目来源:**小米
答案1:
Golang协程池是一种用于管理和优化并发性能的数据结构,通过限制同时运行的goroutine数量来防止资源耗尽。其基本实现思路包括使用channel作为任务队列,以及固定数量的工作协程处理任务。
具体实现步骤如下:
- 定义任务接口:首先定义一个接口表示任务,每个具体的任务实现这个接口。
- 使用channel作为任务队列:当有任务需要执行时,将这个任务插入到channel中。
- 开启固定数量的工作协程:这些协程从任务队列中获取任务进行处理。
例如,可以参考以下代码示例来实现一个简单的协程池:
package main
import (
"fmt"
)
// Task 定义任务接口
type Task interface {
Execute()
}
// SimpleTask 实现任务接口
type SimpleTask struct {
value int
}
func (t *SimpleTask) Execute() {
fmt.Println("执行任务:", t.value )
}
func main() {
// 创建任务队列
taskQueue := make(chan Task, 10)
// 开启固定数量的工作协程
for i := 0; i < 5; i++ {
go func() {
for task := range taskQueue {
task.Execute()
}
}()
}
// 提交任务
for i := 0; i < 20; i++ {
task := &SimpleTask{value: i}
taskQueue <- task
}
close(taskQueue)
}
这个示例展示了如何创建一个简单的协程池,通过channel传递任务,并由多个工作协程并行处理这些任务。
答案2:
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
// Task 任务接口
type Task interface {
Execute()
}
// Pool 协程池
type Pool struct {
TaskChannel chan Task // 任务队列
}
// NewPool 创建一个协程池
func NewPool(cap ...int) *Pool {
// 获取 worker 数量
var n int
if len(cap) > 0 {
n = cap[0]
}
if n == 0 {
n = runtime.NumCPU()
}
p := &Pool{
TaskChannel: make(chan Task),
}
// 创建指定数量 worker 从任务队列取出任务执行
for i := 0; i < n; i++ {
go func() {
for task := range p.TaskChannel {
task.Execute()
}
}()
}
return p
}
// Submit 提交任务
func (p *Pool) Submit(t Task) {
p.TaskChannel <- t
}
// EatFood 吃饭任务
type EatFood struct {
wg *sync.WaitGroup
}
func (e *EatFood) Execute() {
defer e.wg.Done()
fmt.Println("eat cost 3 seconds")
time.Sleep(3 * time.Second)
}
// WashFeet 洗脚任务
type WashFeet struct {
wg *sync.WaitGroup
}
func (w *WashFeet) Execute() {
defer w.wg.Done()
fmt.Println("wash feet cost 3 seconds")
time.Sleep(3 * time.Second)
}
// WatchTV 看电视任务
type WatchTV struct {
wg *sync.WaitGroup
}
func (w *WatchTV) Execute() {
defer w.wg.Done()
fmt.Println("watch tv cost 3 seconds")
time.Sleep(3 * time.Second)
}
func main() {
p := NewPool()
var wg sync.WaitGroup
wg.Add(3)
task1 := &EatFood{
wg: &wg,
}
task2 := &WashFeet{
wg: &wg,
}
task3 := &WatchTV{
wg: &wg,
}
p.Submit(task1)
p.Submit(task2)
p.Submit(task3)
// 等待所有任务执行完成
wg.Wait()
}