# 缺陷&BUG

1. 活躍協程數計算錯誤
2. 執行數量和收到計數錯誤
3. QPS陡增和陡降的時候，無法及時增加壓力和回收協程
4. 協程回收存在問題不夠優雅，效率太低

# BUG分析

## 執行數量和收到計數錯誤

``````// ExecuteQps
//  @Description: 執行任務固定次數
//  @param t
//  @param qps
//
func (pool *GorotinesPool) ExecuteQps(t func(), qps int) {
mutiple := qps / pool.SingleTimes
remainder := qps % pool.SingleTimes
for i := 0; i < pool.SingleTimes; i++ {
pool.Execute(func() {
for i := 0; i < mutiple; i++ {
t()
}
})
}
pool.Execute(func() {
for i := 0; i < remainder; i++ {
t()
}
})
}

``````

## 線程回收不優雅

``````
// balance
//  @Description: 平衡活躍協程數
//
func (pool *GorotinesPool) balance() {
if pool.status {
if len(pool.tasks) > 0 && pool.active < int32(pool.Max) {
}
if len(pool.tasks) == 0 && pool.active > int32(pool.Min) {
pool.ReduceWorker()
}
}
}
``````

# 解決方法

## 重寫回收方法

``````
// worker
//  @Description: 開始執行協程
//
func (pool *GorotinesPool) worker() {
defer func() {
if p := recover(); p != nil {
}
}()
Fun:
for {
select {
t()
case <-time.After(pool.MaxIdle):
if pool.Active > int32(pool.Min) {
break Fun
}
}
}
}
``````

## 協程增加效率

1. 增加掃描後單次增加協程數量，增加等待`channel`數量等量的協程數
2. 調整`func (pool *GorotinesPool) Execute(t func()) error`合併任務的算法，採取固定的數量合併方案

``````// balance
//  @Description: 平衡活躍協程數
//
func (pool *GorotinesPool) balance() {
if pool.status {
if len(pool.tasks) > 0 && pool.Active < int32(pool.Max) {
for i := 0; i < len(pool.tasks); i++ {
if int(pool.Active) < pool.Max {
}
}
}
}
}
``````

``````// ExecuteQps
//  @Description: 執行任務固定次數
//  @param t
//  @param qps
//
func (pool *GorotinesPool) ExecuteQps(t func(), qps int) {
mutiple := qps / pool.SingleTimes
remainder := qps % pool.SingleTimes
for i := 0; i < mutiple; i++ {
pool.Execute(func() {
for i := 0; i < pool.SingleTimes; i++ {
t()
}
})
}
pool.Execute(func() {
for i := 0; i < remainder; i++ {
t()
}
})
}

``````

# 完整代碼

``````package execute

import (
"errors"
"funtester/ftool"   "log"   "sync/atomic"   "time")

type GorotinesPool struct {
Max          int
Min          int
status       bool
Active       int32
ExecuteTotal int32
SingleTimes  int
MaxIdle      time.Duration
}

const (
)

// GetPool
//  @Description: 創建線程池
//  @param max 最大協程數
//  @param min 最小協程數
//  @param timeout 添加任務超時時間，單位s
//  @return *GorotinesPool
//
func GetPool(max, min, maxWaitTask, timeout, maxIdle int) *GorotinesPool {
p := &GorotinesPool{
Max:          max,
Min:          min,
status:       true,
Active:       0,
ExecuteTotal: 0,
SingleTimes:  10,
MaxIdle:      time.Duration(maxIdle) * time.Second,
}
for i := 0; i < min; i++ {
}
go func() {
for {
if !p.status {
break
}
ftool.Sleep(1000)
p.balance()
}
}()
return p
}

// worker
//  @Description: 開始執行協程
//
func (pool *GorotinesPool) worker() {
defer func() {
if p := recover(); p != nil {
}
}()
Fun:
for {
select {
t()
case <-time.After(pool.MaxIdle):
if pool.Active > int32(pool.Min) {
break Fun
}
}
}
}

// Execute
//  @Description: 執行任務
//  @param t
//  @return error
//
func (pool *GorotinesPool) Execute(t func()) error {
if pool.status {
select {
t()
}:
return nil
}
} else {
return errors.New("pools is down")
}
}

// Wait
//  @Description: 結束等待任務完成
//
func (pool *GorotinesPool) Wait() {
pool.status = false
Fun:
for {
if len(pool.tasks) == 0 || pool.Active == 0 {
break Fun
}
ftool.Sleep(1000)
}
log.Printf("execute: %d", pool.ExecuteTotal)
}

//  @Description: 添加worker,協程數加1
//
go pool.worker()
}

// balance
//  @Description: 平衡活躍協程數
//
func (pool *GorotinesPool) balance() {
if pool.status {
if len(pool.tasks) > 0 && pool.Active < int32(pool.Max) {
for i := 0; i < len(pool.tasks); i++ {
if int(pool.Active) < pool.Max {
}
}
}
}
}

// ExecuteQps
//  @Description: 執行任務固定次數
//  @param t
//  @param qps
//
func (pool *GorotinesPool) ExecuteQps(t func(), qps int) {
mutiple := qps / pool.SingleTimes
remainder := qps % pool.SingleTimes
for i := 0; i < mutiple; i++ {
pool.Execute(func() {
for i := 0; i < pool.SingleTimes; i++ {
t()
}
})
}
pool.Execute(func() {