1.1.1. worker pool(goroutine池)

  • 本质上是生产者消费者模型
  • 可以有效控制goroutine数量,防止暴涨
  • 需求:
    • 计算一个数字的各个位数之和,例如数字123,结果为1+2+3=6
    • 随机生成数字进行计算
  • 控制台输出结果如下:

image.png

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. )
  6. type Job struct {
  7. // id
  8. Id int
  9. // 需要计算的随机数
  10. RandNum int
  11. }
  12. type Result struct {
  13. // 这里必须传对象实例
  14. job *Job
  15. // 求和
  16. sum int
  17. }
  18. func main() {
  19. // 需要2个管道
  20. // 1.job管道
  21. jobChan := make(chan *Job, 128)
  22. // 2.结果管道
  23. resultChan := make(chan *Result, 128)
  24. // 3.创建工作池
  25. createPool(64, jobChan, resultChan)
  26. // 4.开个打印的协程
  27. go func(resultChan chan *Result) {
  28. // 遍历结果管道打印
  29. for result := range resultChan {
  30. fmt.Printf("job id:%v randnum:%v result:%d\n", result.job.Id,
  31. result.job.RandNum, result.sum)
  32. }
  33. }(resultChan)
  34. var id int
  35. // 循环创建job,输入到管道
  36. for {
  37. id++
  38. // 生成随机数
  39. r_num := rand.Int()
  40. job := &Job{
  41. Id: id,
  42. RandNum: r_num,
  43. }
  44. jobChan <- job
  45. }
  46. }
  47. // 创建工作池
  48. // 参数1:开几个协程
  49. func createPool(num int, jobChan chan *Job, resultChan chan *Result) {
  50. // 根据开协程个数,去跑运行
  51. for i := 0; i < num; i++ {
  52. go func(jobChan chan *Job, resultChan chan *Result) {
  53. // 执行运算
  54. // 遍历job管道所有数据,进行相加
  55. for job := range jobChan {
  56. // 随机数接过来
  57. r_num := job.RandNum
  58. // 随机数每一位相加
  59. // 定义返回值
  60. var sum int
  61. for r_num != 0 {
  62. tmp := r_num % 10
  63. sum += tmp
  64. r_num /= 10
  65. }
  66. // 想要的结果是Result
  67. r := &Result{
  68. job: job,
  69. sum: sum,
  70. }
  71. //运算结果扔到管道
  72. resultChan <- r
  73. }
  74. }(jobChan, resultChan)
  75. }
  76. }