zoukankan      html  css  js  c++  java
  • 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





  • 相关阅读:
    微信小程序中的iPhone X适配问题
    微信小程序例子-保存图片到手机相册
    微信小程序客服消息使用指南
    移动APP 微信支付完整过程(wxPay 方案一)
    promise原理及使用方法
    apicloud UISearchBar 使用方法
    数据库死锁及解决方法
    js replace使用及正则表达式使用
    POI Workbook接口和HSSFWorkbook对象和XSSFWorkbook对象操作相应excel版本
    HSSFWorkbook 模版使用
  • 原文地址:https://www.cnblogs.com/netuml/p/9063239.html
Copyright © 2011-2022 走看看