golang 多个worker正常关闭的示例

 

代码如下,如有问题请联系 baibaibai_000@163.com
package work_test

import (
    "math/rand"
    "runtime"
    "sync"
    "testing"
    "time"
)

// TestWorker
// test目的:展示当多个worker同时处理一个通道的任务,被关闭时,通道剩余的任务需要被全部处理
func TestWorker(t *testing.T) {

    rand.Seed(time.Now().UnixNano())

    // 虚拟的处理task的函数
    work := func(t int) {

    }

    // 任务通道
    taskChan := make(chan int, 1024)

    // 关闭
    closeChan := make(chan struct{})
    wg := sync.WaitGroup{}

    // worker个数
    workerNum := runtime.NumCPU()

    // 起多个worker来处理taskChan的事务
    for i := 0; i < workerNum; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()

        LOOPING:
            for {
                select {
                case t := <-taskChan: //处理task
                    work(t)
                case <-closeChan: //收到外界关闭的事件
                    // 继续处理taskChan剩余的task,直到通道为空
                    for hasTask := true; hasTask; {
                        select {
                        case t := <-taskChan:
                            work(t)
                        default:
                            hasTask = false
                        }
                    }
                    break LOOPING
                }
            }

        }()

    }

    // 填充任务
    go func() {
        ticker := time.NewTicker(time.Millisecond * time.Duration(1))
        defer ticker.Stop()

        for {
            select {
            case <-ticker.C:
                taskChan <- 1
            case <-closeChan:
                return
            }
        }

    }()

    // 随机个事件后关闭
    time.Sleep(time.Duration(2+rand.Int()%4) * time.Second)
    close(closeChan)

    wg.Wait()

    // 如果taskChan还有没处理的任务就失败了
    if len(taskChan) > 0 {
        t.FailNow()
    }

}

 

posted @ 2019-01-29 17:29  MrBlue  阅读(358)  评论(0编辑  收藏  举报