• go context包的WithTimeout和WithCancel的使用


    1、WaitGroup

      它是一种控制并发的方式,它的这种方式是控制多个goroutine同时完成。

    func main() {
    	var wg sync.WaitGroup
    	wg.Add(2)
    	go func() {
    		time.Sleep(2*time.Second)
    		fmt.Println("1号完成")
    		wg.Done()
    	}()
    	go func() {
    		time.Sleep(2*time.Second)
    		fmt.Println("2号完成")
    		wg.Done()
    	}()
    	wg.Wait()
    	fmt.Println("好了,大家都干完了,放工")
    }
    

      一个很简单的例子,一定要例子中的2个goroutine同时做完,才算是完成,先做好的就要等着其他未完成的,所有的goroutine要都全部完成才可以。

    2、chan通知

      我们都知道一个goroutine启动后,我们是无法控制他的,大部分情况是等待它自己结束,那么如果这个goroutine是一个不会自己结束的后台goroutine呢?比如监控等,会一直运行的。

      这种情况化,一直傻瓜式的办法是全局变量,其他地方通过修改这个变量完成结束通知,然后后台goroutine不停的检查这个变量,如果发现被通知关闭了,就自我结束。

      这种方式也可以,但是首先我们要保证这个变量在多线程下的安全,基于此,有一种更好的方式:chan + select 。

    func main() {
    	stop := make(chan bool)
    	go func() {
    		for {
    			select {
    			case <-stop:
    				fmt.Println("监控退出,停止了...")
    				return
    			default:
    				fmt.Println("goroutine监控中...")
    				time.Sleep(2 * time.Second)
    			}
    		}
    	}()
    	time.Sleep(10 * time.Second)
    	fmt.Println("可以了,通知监控停止")
    	stop<- true
    	//为了检测监控过是否停止,如果没有监控输出,就表示停止了
    	time.Sleep(5 * time.Second)
    }
    

      

    3、WithTimeout 超时自动取消方法

       当执行一个go 协程时,超时自动取消协程

    // 模拟一个最小执行时间的阻塞函数
    func inc(a int) int {
    	res := a + 1                // 虽然我只做了一次简单的 +1 的运算,
    	time.Sleep(1 * time.Second) // 但是由于我的机器指令集中没有这条指令,
    	// 所以在我执行了 1000000000 条机器指令, 续了 1s 之后, 我才终于得到结果。B)
    	return res
    }
    
    // 向外部提供的阻塞接口
    // 计算 a + b, 注意 a, b 均不能为负
    // 如果计算被中断, 则返回 -1
    func Add(ctx context.Context, a, b int) int {
    	res := 0
    	for i := 0; i < a; i++ {
    		res = inc(res)
    		select {
    		case <-ctx.Done():
    			return -1
    		default:
    		}
    	}
    	for i := 0; i < b; i++ {
    		res = inc(res)
    		select {
    		case <-ctx.Done():
    			return -1
    		default:
    		}
    	}
    	return res
    }
    

      计算 a+b

    func main() {
    	// 使用开放的 API 计算 a+b
    	a := 1
    	b := 2
    	timeout := 2 * time.Second
    	ctx, _ := context.WithTimeout(context.Background(), timeout)
    	res := Add(ctx, 1, 2)
    	fmt.Printf("Compute: %d+%d, result: %d
    ", a, b, res)
    }
    

      输出结果:Compute: 1+2, result: -1

    4、WithCancel 手动取消方法
    func main() {
    	// 手动取消
    	a := 1
    	b := 2
    	ctx, cancel := context.WithCancel(context.Background())
    	go func() {
    		time.Sleep(2 * time.Second)
    		cancel() // 在调用处主动取消
    	}()
    	res := Add(ctx, 1, 2)
    	fmt.Printf("Compute: %d+%d, result: %d
    ", a, b, res)
    }
    

      输出结果:Compute: 1+2, result: -1





  • 相关阅读:
    ASE19团队项目 beta阶段 model组 scrum report list
    ASE19团队项目 beta阶段 model组 scrum7 记录
    ASE19团队项目 beta阶段 model组 scrum6 记录
    ASE19团队项目 beta阶段 model组 scrum5 记录
    ASE19团队项目 beta阶段 model组 scrum4 记录
    ASE19团队项目 beta阶段 model组 scrum3 记录
    ASE19团队项目 beta阶段 model组 scrum2 记录
    ASE19团队项目 beta阶段 model组 scrum1 记录
    【ASE模型组】Hint::neural 模型与case study
    【ASE高级软件工程】第二次结对作业
  • 原文地址:https://www.cnblogs.com/netuml/p/9063239.html
Copyright © 2020-2023  润新知