go实现协程池

参考解析

**题目来源:**小米

答案1:

Golang协程池是一种用于管理和优化并发性能的数据结构,通过限制同时运行的goroutine数量来防止资源耗尽。其基本实现思路包括使用channel作为任务队列,以及固定数量的工作协程处理任务。

具体实现步骤如下:

  1. 定义任务接口:首先定义一个接口表示任务,每个具体的任务实现这个接口。
  2. 使用channel作为任务队列:当有任务需要执行时,将这个任务插入到channel中。
  3. 开启固定数量的工作协程:这些协程从任务队列中获取任务进行处理。

例如,可以参考以下代码示例来实现一个简单的协程池:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. // Task 定义任务接口
  6. type Task interface {
  7. Execute()
  8. }
  9. // SimpleTask 实现任务接口
  10. type SimpleTask struct {
  11. value int
  12. }
  13. func (t *SimpleTask) Execute() {
  14. fmt.Println("执行任务:", t.value )
  15. }
  16. func main() {
  17. // 创建任务队列
  18. taskQueue := make(chan Task, 10)
  19. // 开启固定数量的工作协程
  20. for i := 0; i < 5; i++ {
  21. go func() {
  22. for task := range taskQueue {
  23. task.Execute()
  24. }
  25. }()
  26. }
  27. // 提交任务
  28. for i := 0; i < 20; i++ {
  29. task := &SimpleTask{value: i}
  30. taskQueue <- task
  31. }
  32. close(taskQueue)
  33. }

这个示例展示了如何创建一个简单的协程池,通过channel传递任务,并由多个工作协程并行处理这些任务。

答案2:

  1. package main
  2. import (
  3. "fmt"
  4. "runtime"
  5. "sync"
  6. "time"
  7. )
  8. // Task 任务接口
  9. type Task interface {
  10. Execute()
  11. }
  12. // Pool 协程池
  13. type Pool struct {
  14. TaskChannel chan Task // 任务队列
  15. }
  16. // NewPool 创建一个协程池
  17. func NewPool(cap ...int) *Pool {
  18. // 获取 worker 数量
  19. var n int
  20. if len(cap) > 0 {
  21. n = cap[0]
  22. }
  23. if n == 0 {
  24. n = runtime.NumCPU()
  25. }
  26. p := &Pool{
  27. TaskChannel: make(chan Task),
  28. }
  29. // 创建指定数量 worker 从任务队列取出任务执行
  30. for i := 0; i < n; i++ {
  31. go func() {
  32. for task := range p.TaskChannel {
  33. task.Execute()
  34. }
  35. }()
  36. }
  37. return p
  38. }
  39. // Submit 提交任务
  40. func (p *Pool) Submit(t Task) {
  41. p.TaskChannel <- t
  42. }
  43. // EatFood 吃饭任务
  44. type EatFood struct {
  45. wg *sync.WaitGroup
  46. }
  47. func (e *EatFood) Execute() {
  48. defer e.wg.Done()
  49. fmt.Println("eat cost 3 seconds")
  50. time.Sleep(3 * time.Second)
  51. }
  52. // WashFeet 洗脚任务
  53. type WashFeet struct {
  54. wg *sync.WaitGroup
  55. }
  56. func (w *WashFeet) Execute() {
  57. defer w.wg.Done()
  58. fmt.Println("wash feet cost 3 seconds")
  59. time.Sleep(3 * time.Second)
  60. }
  61. // WatchTV 看电视任务
  62. type WatchTV struct {
  63. wg *sync.WaitGroup
  64. }
  65. func (w *WatchTV) Execute() {
  66. defer w.wg.Done()
  67. fmt.Println("watch tv cost 3 seconds")
  68. time.Sleep(3 * time.Second)
  69. }
  70. func main() {
  71. p := NewPool()
  72. var wg sync.WaitGroup
  73. wg.Add(3)
  74. task1 := &EatFood{
  75. wg: &wg,
  76. }
  77. task2 := &WashFeet{
  78. wg: &wg,
  79. }
  80. task3 := &WatchTV{
  81. wg: &wg,
  82. }
  83. p.Submit(task1)
  84. p.Submit(task2)
  85. p.Submit(task3)
  86. // 等待所有任务执行完成
  87. wg.Wait()
  88. }