求 go 并发限制的最佳实现

2021-02-08 12:01:29 +08:00
 monkeyWie

情况如下: 有 N 个任务,每个任务执行完都会返回结果或者 error,通过固定的(M)协程去执行,如果其中有一个任务返回 error 时立即结束,否则全部执行完成时返回结果列表。

我自己写了一版,感觉有点复杂:https://play.golang.org/p/ono1S04XupK

不知道各位有没有什么更简单的实现。

7019 次点击
所在节点    Go 编程语言
70 条回复
ToPoGE
2021-02-08 12:16:33 +08:00
context 不就可以实现吗
cloudfstrife
2021-02-08 12:26:53 +08:00
errgroup 了解一下
xylophone21
2021-02-08 12:30:21 +08:00
一起探讨,如果 M 不是大到离谱,是否需要控制 M ?还是无脑 go 就好了,因为这样感觉就是 go 程池 /线程池了,有点像把 go 程当线程用了?
sunorg
2021-02-08 12:44:23 +08:00
不是 channel 就可以实现了吗?
monkeyWie
2021-02-08 13:22:19 +08:00
@ToPoGE context 实现不了等待任务全部执行完成吧
monkeyWie
2021-02-08 13:25:00 +08:00
@xylophone21 现在就是 M 如果太大了服务器会顶不住,比如并发查询 sql
monkeyWie
2021-02-08 13:34:51 +08:00
@cloudfstrife errgroup 我试了下,第一不能限制并发数,第二不能在发生错误时立即返回。
baodaren8
2021-02-08 13:35:46 +08:00
借楼问一下,我怎么不能发帖了。。
coool
2021-02-08 13:45:42 +08:00
@baodaren8 我也不能发了
ToPoGE
2021-02-08 13:52:03 +08:00
@monkeyWie context 配合 waitGRoup,就可以做到失败一个全干掉,全完成,返回
MadbookPro
2021-02-08 14:00:54 +08:00
一个 err chan 用来通知 root goroutine 发生错误,然后 root context 退出; wait group 用来做全部完成检查。
这样何如?
fatedier
2021-02-08 14:04:21 +08:00
MadbookPro
2021-02-08 14:04:47 +08:00
哦还有并发控制。
taskChannel + workerChannel,这样 wait group 也不需要了
mogg
2021-02-08 14:23:54 +08:00
线程池+channel,收到错误消息停止向队列里发送消息。
想要立刻回收,主线程直接 stop 线程池里所有线程,否则等待运行中线程跑完
monkeyWie
2021-02-08 14:27:43 +08:00
@ToPoGE @MadbookPro @mogg
直接上代码吧,这样说不明白🤣
LoNeFong
2021-02-08 14:29:07 +08:00
errgroup + 1
Claar
2021-02-08 14:37:21 +08:00
并发控制:协程池
消息传递:channel
还有等待协程结束再结束 main 函数:sync.
甚至可以子任务报错直接 exit
ToPoGE
2021-02-08 14:38:59 +08:00
@monkeyWie 那你用 errgroup 把,go 官方标准库中的,看文档直接用,就是 context 和 waitGroup 结合的
ppphp
2021-02-08 14:48:36 +08:00
看不到代码。。。我的思路是,for 循环几个 goroutine,select 的时候,先从 errchannel 里看 err,然后 default 里从 taskchannel 里拿 task
mogg
2021-02-08 15:48:18 +08:00
```go
var wg sync.WaitGroup
pool := makePool(pollSize)
func() {
for i := 0; i < runTimes; i++ {
select {
case <-errChan:
fmt.Println("error")
pool.Stop()
return
default:
wg.Add(1)
poll.Submit(task)
}
}
}()
if pool.IsRunning()
wg.Wait()
```
我觉得核心就是这样一个结构,不过 go 没用过线程池,可以看看有什么库

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/752304

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX