哈喽,大家好,我是asong;前几天逛github发现了一个有趣的并发库-conc,其目标是:,从简介上看主要封装功能如下:,接下来就区分模块来介绍一下这个库;,仓库地址:https://github.com/sourcegraph/conc,Go语言标准库有提供sync.waitGroup控制等待goroutine,我们一般会写出如下代码:,上述代码我们需要些一堆重复代码,并且需要单独在每一个func中处理recover逻辑,所以conc库对其进行了封装,代码简化如下:,conc库封装也比较简单,结构如下:,其自己实现了Catcher类型对recover逻辑进行了封装,封装思路如下:,recovered是原子指针类型,RecoveredPanic是捕获的recover封装,封装了堆栈等信息:,提供了Try方法执行方法,只会记录第一个panic的gououtine信息:,提供了Repanic()方法用来重放捕获的panic:,waitGroup对此也分别提供了Wait()、WaitAndRecover()方法:,wait方法只要有一个goroutine发生panic就会向上抛出panic,比较简单粗暴;,waitAndRecover方法只有有一个goroutine发生panic就会返回第一个recover的gouroutine信息;,总结:conc库对waitGrouop的封装总体是比较不错的,可以减少重复的代码;,conc提供了几种类型的worker池:,我们来看一个简单的例子:,在创建pool时有如下方法可以调用:,pool的基础结构如下:,limiter是控制器,用chan来控制goroutine的数量:,pool的核心逻辑也比较简单,如果没有设置limiter,那么就看有没有空闲的worker,否则就创建一个新的worker,然后投递任务进去;,如果设置了limiter,达到了limiter worker数量上限,就把任务投递给空闲的worker,没有空闲就阻塞等着;,这里work使用的是一个无缓冲的channel,这种复用方式很巧妙,如果goroutine执行很快避免创建过多的goroutine;,使用pool处理任务不能保证有序性,conc库又提供了Stream方法,返回结果可以保持顺序;,Steam的实现也是依赖于pool,在此基础上做了封装保证结果的顺序性,先看一个例子:,stream的结构如下:,queue是一个channel类型,callbackCh也是channel类型 – chan func():,在提交goroutine时按照顺序生成callbackCh传递结果:,conc库提供了ForEach方法可以优雅的并发处理切片,看一下官方的例子:,,conc库使用泛型进行了封装,我们只需要关注handle代码即可,避免冗余代码,我们自己动手写一个例子:,ForEach内部实现为Iterator结构及核心逻辑如下:,可以设置并发的goroutine数量,默认取的是GOMAXPROCS ,也可以自定义传参;,并发执行这块设计的很巧妙,仅创建了一个闭包,通过atomic控制idx,避免频繁触发GC;,conc库提供的map方法可以得到对切片中元素结果,官方例子:,,使用map可以提高代码的可读性,并且减少了冗余代码,自己写个例子:,map的实现也依赖于Iterator,也是调用的ForEachIdx方法,区别于ForEach是记录处理结果;,花了小半天时间看了一下这个库,很多设计点值得我们学习,总结一下我学习到的知识点:,小伙伴们有时间可以看一下这个并发库,学习其中的优点,慢慢进步~
文章版权声明
1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/19195.html
2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈
3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)
4 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别