12 go 并发编程二

1.select的用法。

func g1(ch1 chan struct{}) {

    time.Sleep(3 * time.Second)
    ch1 <- struct{}{}
}
func g2(ch2 chan struct{}) {

    time.Sleep(4 * time.Second)
    ch2 <- struct{}{}
}
func main() {
    g1Channel := make(chan struct{})
    g2Channel := make(chan struct{})
    go g1(g1Channel)
    go g2(g2Channel)
    // 我要监控多个channel任何一个有值都知道
    //1. 某一个分支就绪了就执行该分支
    //2. 如果两个都就绪了 先执行哪个 随机的 目的是防止饥饿  防止一直只能拿到一个固定的锁    tm := time.NewTimer(time.Second * 5)
    select {
    case <-g1Channel:
        fmt.Println("g1 done")
    case <-g2Channel:
        fmt.Println("g2 done")
    case <-tm.C:
        fmt.Println("default")
        return
    }
}

 

var wg sync.WaitGroup
var stop bool

func cpuInfo() {
    defer wg.Done()
    for {
        if stop {
            break
        }
        time.Sleep(time.Second)
        fmt.Println("cpu 监控")
    }
}

func main() {
    wg.Add(1)
    go cpuInfo()
    time.Sleep(time.Second * 3)
    stop = true
    wg.Wait()
}

 

var wg sync.WaitGroup
var stop = make(chan struct{})

func cpuInfo() {
    defer wg.Done()
    for {
        select {
        case <-stop:
            fmt.Println("退出cpu监控")
            return
        default:
            time.Sleep(time.Second)
            fmt.Println("cpu 监控")
        }

    }
}

func main() {
    wg.Add(1)
    go cpuInfo()
    time.Sleep(time.Second * 3)
    stop <- struct{}{}
    wg.Wait()
}

2. contex的用法。

在Go语言中,context包提供了一种在多个goroutine之间传递请求范围的值、取消信号以及截止时间的方式。context.Context接口是Go语言中用于控制goroutine生命周期和传递请求范围的数据的。

context.Background()函数返回一个非关联到任何取消信号的空context。这个空context可以用来作为其他context的父context,它永远不会被取消,也没有值可以被传递。

当你看到代码:

go
ctx1, _ := context.WithTimeout(context.Background(), time.Second*6)
这里的context.Background()创建了一个空的context,然后context.WithTimeout函数被用来创建一个新的context,这个新的context有一个截止时间。在这个例子中,截止时间被设置为6秒。

context.WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)函数接受两个参数:

parent:父context,用于创建一个新的context。在这里,父context是一个空的context,由context.Background()返回。

timeout:超时时间,表示新创建的context将在指定的时间后自动取消。

函数返回两个值:

一个新的Context,它在指定的超时时间后会被取消。

一个CancelFunc,可以用来手动取消这个context。

 

package main
import (
    "context"
    "fmt"
    "sync"
    "time"
)
var wg sync.WaitGroup
var stop = make(chan struct{})
func cpuInfo(ctx context.Context) {
    defer wg.Done()
    for {
        select {
        case <-ctx.Done():
            fmt.Println("退出cpu监控")
            return
        default:
            time.Sleep(time.Second)
            fmt.Println("cpu 监控")
        }

    }
}
// context解决 父的线程给子的线程发送一些消息
// context 提供了三种函数WithCancel  WithTimeout  WithValue
func main() {
    wg.Add(1)
    ctx, cancel := context.WithCancel(context.Background())
    go cpuInfo(ctx)
    time.Sleep(time.Second * 3)
    cancel()
    wg.Wait()
}

 主动取消

var wg sync.WaitGroup
var stop = make(chan struct{})

func cpuInfo(ctx context.Context) {
    defer wg.Done()
    for {
        select {
        case <-ctx.Done():
            fmt.Println("退出cpu监控")
            return
        default:
            time.Sleep(time.Second)
            fmt.Println("cpu 监控")
        }

    }
}

// context解决 父的线程给子的线程发送一些消息
func main() {
    wg.Add(1)
    //context 提供了三种函数WithCancel  WithTimeout  WithValue
    // 如果你的goroutine、函数 希望被控制。超时 传值的时候不希望影响原来接口信息的时候
    // 函数第一个值尽量加上context
    ctx, cancel := context.WithCancel(context.Background())
    ctx1, _ := context.WithCancel(ctx)
    go cpuInfo(ctx1)
    time.Sleep(time.Second * 3)
    cancel()
    wg.Wait()
}

 

 

context.WithTimeout 超时取消
func main() {
    wg.Add(1)
    //context 提供了三种函数WithCancel  WithTimeout  WithValue
    // 如果你的goroutine、函数 希望被控制。超时 传值的时候不希望影响原来接口信息的时候
    // 函数第一个值尽量加上context
    // 主动超时取消
    ctx1, _ := context.WithTimeout(context.Background(), time.Second*6)
    go cpuInfo(ctx1)

    wg.Wait()
}

 

context.WithValue 传值
package main

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

var wg sync.WaitGroup

//var stop = make(chan struct{})

func cpuInfo(ctx context.Context) {
    v := ctx.Value("requestId")
    fmt.Printf("%s \n\r", v)
    defer wg.Done()
    for {
        select {
        case <-ctx.Done():
            fmt.Println("退出cpu监控")
            return
        default:
            time.Sleep(time.Second)
            fmt.Println("cpu 监控")
        }

    }
}

// context解决 父的线程给子的线程发送一些消息
func main() {
    wg.Add(1)
    //context 提供了三种函数WithCancel  WithTimeout  WithValue
    // 如果你的goroutine、函数 希望被控制。超时 传值的时候不希望影响原来接口信息的时候
    // 函数第一个值尽量加上context
    // 主动超时取消
    ctx1, _ := context.WithTimeout(context.Background(), time.Second*6)
    ctx2 := context.WithValue(ctx1, "requestId", "5748ghjgfj34rf")
    go cpuInfo(ctx2)
    // context.WithDeadline() 在指定时间取消 在12:00点整取消

    wg.Wait()
}

 

posted @ 2024-09-30 11:24  滴滴滴  阅读(3)  评论(0编辑  收藏  举报