0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

接口调用并发执行十个任务总结

马哥Linux运维 来源:网络整理 2023-11-15 10:37 次阅读

需求

一个接口调用时,接收到一个列表,十个元素,需要并发执行十个任务,每个任务都要返回执行的结果和异常,然后对返回的结果装填到一个切片列表里,统一返回结果。

需要协程处理的结构体

type Order struct {  
  Name string `json:"name"`  
  Id int `json:"id"`  
}

确定通道数量

一般按入参的需要处理的元素数量为准

taskNum:=10

初始化通道

orderCh := make(chan Order, taskNum) //接收返回的结果
errCh:=make(chanerror,taskNum)//接收返回的异常

发起执行,我们使用sync.WaitGroup来监听执行情况

wg := sync.WaitGroup{}
for i:=0; i < taskNum; i++ {
   wg.Add(1)
   go func() {
     defer wg.Done()
     if i == 3 {//模拟当i=3的时候,返回一个异常
         err := errors.New("there is an error")
         errCh <- err 
         return
     }
     //组装返回结果
     res := Order{  
         Name: "num: " + strconv.Itoa(i),  
         Id: i,  
         }
     orderCh <- res    
  }()
}
wg.Wait() //等待所有任务执行完毕

使用for-select接收执行结果

orderList := make([]Order, taskNum)
for i:=0; i

1,超时问题

任务执行过程中,需要控制每个任务的执行时间,不能超过一定范围,我们用定时器来解决这个问题

timeoutTime := time.Second * 3  //超时时间
taskTimer := time.NewTimer(timeoutTime) //初始化定时器
orderList := make([]Order, taskNum)
for i:=0; i

2, 协程panic问题

主程序是无法捕捉协程内的panic,因此如果不手动处理,就会发生协程内panic导致整个程序中止的情况,我们在defer里处理

for i:=0; i < taskNum; i++ {
   wg.Add(1)
   go func() {
     defer func () {
      wg.Done()
      //协程内单独捕捉异常  
      if r := recover(); r != nil {  
        err := errors.New(fmt.Sprintf("System panic:%v", r))  
        errCh <- err //此处将panic信息转为err返回,也可以按需求和异常等级进行处理
        return
      }
     }()
   ........
  }()
}

3, 顺序问题

返回的列表元素的顺序,需要跟传参的列表顺序保持一致,这时我们需要定义个带序号的结构体

// 需要记录原始顺序的时候,定义个带编号的结构体  
type OrderWithSeq struct {  
    Seq int  
    OrderItem Order  
}  
//重写相关排序类型
type BySeq []OrderWithSeq  
  
func (a BySeq) Len() int {  
    return len(a)  
}  
func (a BySeq) Swap(i, j int) {  
    a[i], a[j] = a[j], a[i]  
}  
func (a BySeq) Less(i, j int) bool {  
    return a[i].Seq < a[j].Seq  
}
// 调整返回结果
orderCh := make(chan OrderWithSeq, taskNum) //接收带序号的结构体
//在执行任务时,加入序号
for i:=0; i < taskNum; i++ {
   i:= i
   wg.Add(1)
   go func() {
     ····
     //组装返回结果
     res := Order{  
         Name: "num: " + strconv.Itoa(i),  
         Id: i,  
         }
     orderCh <-OrderWithSeq {
         Seq: i, //带上i这个序号
         OrderItem: res,
     }
  }()
 //接收信息,也按带序号的结构体进行组装
 orderSeqList := make([]OrderWithSeq, taskNum)
 for i:=0; i

总结

标准模板如下:

type Order struct {  
  Name string `json:"name"`  
  Id int `json:"id"`  
}


// 需要记录原始顺序的时候,定义个带编号的结构体  
type OrderWithSeq struct {  
    Seq int  
    OrderItem Order  
}  
//重写相关排序类型
type BySeq []OrderWithSeq  
  
func (a BySeq) Len() int {  
    return len(a)  
}  
func (a BySeq) Swap(i, j int) {  
    a[i], a[j] = a[j], a[i]  
}  
func (a BySeq) Less(i, j int) bool {  
    return a[i].Seq < a[j].Seq  
}


taskNum := 10 
orderCh := make(chan OrderWithSeq, taskNum) //接收带序号的结构体
errCh := make(chan error, taskNum) //接收返回的异常
wg := sync.WaitGroup{}
//在执行任务时,加入序号
for i:=0; i < taskNum; i++ {
   i:= i
   wg.Add(1)
   go func() {
     defer func () {
      wg.Done()
      //协程内单独捕捉异常  
      if r := recover(); r != nil {  
        err := errors.New(fmt.Sprintf("System panic:%v", r))  
        errCh <- err //此处将panic信息转为err返回,也可以按需求和异常等级进行处理
        return
      }
     }()
     //组装返回结果
     res := Order{  
         Name: "num: " + strconv.Itoa(i),  
         Id: i,  
         }
     orderCh <-OrderWithSeq {
         Seq: i, //带上i这个序号
         OrderItem: res,
     }
  }()
 wg.Wait()
  //接收信息,也按带序号的结构体进行组装
 orderSeqList := make([]OrderWithSeq, taskNum)
 timeoutTime := time.Second * 3 
 taskTimer := time.NewTimer(timeoutTime)
 for i:=0; i
                                        
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    8575

    浏览量

    151021
  • 定时器
    +关注

    关注

    23

    文章

    3246

    浏览量

    114721

原文标题:总结

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    EMC的十个知识问答

    EMC的十个为什么, 为什么要对产品做电磁兼容设计?在电磁兼容领域,为什么总是用分贝(dB)的单位描述?为什么频谱分析仪不能观测静电放电等瞬态干扰?
    发表于 11-28 10:58 1201次阅读

    请问一协调器连接十个终端,如何能获取十个终端的短地址?

    本帖最后由 一只耳朵怪 于 2018-5-24 14:22 编辑 一协调器连接十个终端,如何能获取十个终端的短地址,求思路
    发表于 05-22 08:57

    ECG十个电极和12导联

    ECG十个电极和12导联1.对ECG获取心电图信息不是很了解,ECG只有十个电极为什么称作12导联?电极和导联之间有什么关联?2.什么叫做右脚驱动?为什么不能用左脚?3.除了PPG、ECG、还有BCG技术,如果做心率的检测用哪种技术更好?
    发表于 12-08 16:31

    任务编程多任务处理是指什么

    。多任务操作系统使用某种调度策略支持多个任务并发执行。每个任务被创建时分配时间片(几到上百毫秒
    发表于 12-22 08:30

    数码摄像头的十个故障分析案例

    数码摄像头的十个故障分析案例 1.找不到摄像头故障现象 一台电脑检测不到新装的USB接口的摄像头。分析及处理 先查操作系统,再查BIOS、USB接口及安装有
    发表于 05-17 16:44 80次下载

    选用LED驱动电源的十个要点

    选用LED驱动电源的十个要点,如何明智地选择适合驱动LED的电源,是每位工程师在设计时都关心的问题。
    发表于 02-15 15:35 1409次阅读

    开关电源技术的十个关注点

    开关电源的相关知识学习教材资料——开关电源技术的十个关注点
    发表于 09-20 15:44 0次下载

    Dispatch Queue任务执行与Dispatch Source

    导读本文为读《Concurrency Programming Guide》笔记第三篇,在对OS X和iOS应用开发中实现任务异步执行的技术、注意事项、Operation与Dispatch
    发表于 10-11 11:54 0次下载

    实施MES系统能为企业解决的十个问题资料分析

    实施MES系统能为企业解决的十个问题
    发表于 01-04 15:50 7次下载

    十个问题带你了解和掌握java HashMap

    本文档内容介绍了十个问题带你了解和掌握java HashMap及源代码,供参考
    发表于 03-12 15:41 0次下载

    人工智能和人类智能的十个不同之处

    人工智能和人类智能究竟有何不同之处呢?在本文中Sabine Hossenfelder 就从十个方面分析了这两者间的不同。
    的头像 发表于 05-04 09:10 5732次阅读

    智慧城市成功的十个观察结果

    过去几年,全球宣布了数十个智慧城市项目。早期采用者已经在实施他们的智慧城市计划。
    发表于 05-24 11:25 894次阅读

    TCP/IP十个问题

    本文整理了一些TCP/IP协议簇中需要必知必会的大问题,既是面试高频问题,又是程序员必备基础素养。 TCP/IP十个问题 一、TCP/IP模型TCP/IP协议模型(Transmission
    的头像 发表于 11-04 14:46 2444次阅读

    部署无线AP的十个注意事项

    部署无线AP的十个注意事项
    发表于 10-09 14:21 6次下载

    NVIDIA Triton 系列文章(10):模型并发执行

    (concurrent model execution)的调试,这是提升 Triton 服务器性能的最基本任务。  Triton 服务器支持的模型并发能力,包括一模型并发多个推理实例
    的头像 发表于 01-05 11:55 1109次阅读