package main

import (
    "context"
    "fmt"
    "sync"
    "time"
)

func main() {

}

//
//例子中我们通过select判断stop是否接受到值,如果接受到值就表示可以推出停止了,如果没有接受到,
//就会执行default里面的监控逻辑,继续监控,直到收到stop的通知
//以上控制goroutine的方式在大多数情况下可以满足我们的使用,但是也存在很多局限性,比如有很多goroutiine,
//并且这些goroutine还衍生了其他goroutine,此时chan就比较困难解决这样的问题了
func testChan() {
    stop := make(chan bool)
    go func() {
        for {
            select {
            case <-stop:
                fmt.Println("")
                return
            default:
                fmt.Println("groutine监控中...")
                time.Sleep(1 * time.Second)
            }
        }
    }()
    time.Sleep(10 * time.Second)
    fmt.Println("可以了,监控停止了")
    stop <- true
    time.Sleep(5 * time.Second)
}

//以上例子一定要等到两个goroutine同时做完才会全部完成,这种控制并发方式尤其适用于多个goroutine协同做一件事情的时候。
func testWaitGroup() {
    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        time.Sleep(2 * time.Second)
    }()

    go func() {
        defer wg.Done()
        time.Sleep(3 * time.Second)
    }()
    wg.Wait()
    fmt.Println("好了,大家都干完活了")
}

func CancelTest() {
    ctx, cancel := context.WithCancel(context.Background())
    go func(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("协程退出,停止了...")
                return
            default:
                fmt.Println("协程运行中...")
                time.Sleep(2 * time.Second)
            }
        }
    }(ctx)
    time.Sleep(time.Second * 30)
    fmt.Println("两分钟时间到了,关闭子协程")
    cancel()
    time.Sleep(time.Second * 10)
    fmt.Println("演示结束")
}

// TimeOutTest WithTimeout
func TimeOutTest() {
    ctx, _ := context.WithTimeout(context.Background(), time.Minute*1)
    go func(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("协程退出,停止了...")
                return
            default:
                fmt.Println("协程运行中...")
                time.Sleep(2 * time.Second)
            }
        }
    }(ctx)
    time.Sleep(time.Second * 70)
    fmt.Println("演示结束")
}

// DeadLineTest WithDeadline
func DeadLineTest() {
    ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(time.Minute*1))
    go func(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("协程退出,停止了...")
                return
            default:
                fmt.Println("协程运行中...")
                time.Sleep(2 * time.Second)
            }
        }
    }(ctx)
    time.Sleep(time.Second * 70)
    fmt.Println("演示结束")
}

// WithValueTest WithCancel
func WithValueTest() {
    ctx, cancel := context.WithCancel(context.Background())
    //附加值
    valueCtx := context.WithValue(ctx, "test", "子协程1")
    go func(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                //取出值
                fmt.Println(ctx.Value("test"), "监控退出,停止了...")
                return
            default:
                //取出值
                fmt.Println(ctx.Value("test"), "goroutine监控中...")
                time.Sleep(2 * time.Second)
            }
        }
    }(valueCtx)
    time.Sleep(10 * time.Second)
    fmt.Println("可以了,通知监控停止")
    cancel()
    //为了检测监控过是否停止,如果没有监控输出,就表示停止了
    time.Sleep(5 * time.Second)
}

goper
413 声望25 粉丝

go 后端开发