Go 中的简单工作池

2024-01-02

我正在尝试在 go 中实现一个简单的工作池,但不断遇到问题。我想做的就是让一定数量的工人先完成一定数量的工作,然后再做更多的工作。我正在使用的代码类似于:

    jobs := make(chan imageMessage, 1)
    results := make(chan imageMessage, 1)

    for w := 0; w < 2; w++ {
        go worker(jobs, results)
    }

    for j := 0; j < len(images); j++ {
        jobs <- imageMessage{path: paths[j], img: images[j]}
    }
    close(jobs)

    for r := 0; r < len(images); r++ {
        <-results
    }
}

func worker(jobs <-chan imageMessage, results chan<- imageMessage) {
    for j := range jobs {
        processImage(j.path, j.img)
        results <- j
    }
}

我的理解是,这应该创建 2 个工人,一次可以做 1 件“事情”,并且当他们完成这 1 件事情时,他们将继续获得更多的工作,直到没有其他事情可做。但是,我得到fatal error: all goroutines are asleep - deadlock!

如果我将缓冲区设置为像 100 这样的大值,这可以工作,但我希望能够限制一次完成的工作。

我觉得我很接近,但显然缺少一些东西。


问题是你只是开始“耗尽”results频道,一旦您成功发送了频道上的所有作业jobs渠道。但为了让您能够发送所有作业,无论是jobs通道必须有足够大的缓冲区,或者工作协程必须能够从中消耗作业。

但是,worker goroutine 在使用一项工作时,在执行下一项工作之前,会将结果发送到results渠道。如果缓冲区的results通道已满,发送结果会阻塞。

但最后一部分——工人 goroutine 在发送结果时被阻止——只能通过从results通道 – 在您可以发送所有作业之前,您不需要这样做。死锁如果jobs频道和results频道不能容纳你所有的工作。这也解释了为什么如果将缓冲区大小增加到一个大值,它就会起作用:如果作业可以放入缓冲区,则不会发生死锁,并且在所有作业都成功发送后,您的最终循环将耗尽results渠道。

解决方案?在它自己的 goroutine 中运行生成和发送作业,这样您就可以开始从results“立即”通道,无需等待发送所有作业,这意味着工作协程在尝试发送结果时不会永远被阻塞:

go func() {
    for j := 0; j < len(images); j++ {
        jobs <- imageMessage{path: paths[j], img: images[j]}
    }
    close(jobs)
}()

尝试一下去游乐场 https://play.golang.org/p/jvitOGmzpl.

另请查看类似的实现这是 Go 中惯用的工作线程池吗? https://stackoverflow.com/questions/38170852/is-this-an-idiomatic-worker-thread-pool-in-go/38172204#38172204

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go 中的简单工作池 的相关文章

  • 如何关闭 gorm 1.20.0 中的数据库实例

    由于我没有在 Close 函数中找到 gorm 实例 任何帮助将不胜感激 dbURI fmt Sprintf user s password s dbname s port s sslmode s TimeZone s username p
  • 如果在睡眠线程上调用interrupt()会发生什么?

    我有一个线程 然后run I call sleep 如果我中断这个线程会发生什么 MyThread extends Thread public void run try sleep 1000000 catch InterruptedExce
  • 通过 ruby​​ 进程共享变量

    我正在编写一个 gem 其中我必须分叉两个进程来启动两个 webrick 服务器 我想通过基类的类方法启动该服务器 因为应该只运行这两个服务器 而不是多个服务器 在运行时 我想调用这两台服务器上的一些方法来更改变量 我的问题是 我无法通过基
  • 在java中实现你自己的阻塞队列

    我知道这个问题之前已经被问过并回答过很多次了 但我只是无法根据互联网上找到的示例找出窍门 例如this http tutorials jenkov com java concurrency blocking queues html or t
  • C++ 异步线程同时运行

    我是 C 11 中线程的新手 我有两个线程 我想让它们同时启动 我可以想到两种方法 如下 然而 似乎它们都没有按照我的预期工作 他们在启动另一个线程之前启动一个线程 任何提示将不胜感激 另一个问题是我正在研究线程队列 所以我会有两个消费者和
  • select 语句是否保证通道选择的顺序?

    继从这个答案 https stackoverflow com a 25795236 274460 如果一个 goroutine 在两个通道上进行选择 是否保证通道的选择顺序与其发送的顺序相同 我对发送者是单线程的情况特别感兴趣 例如 是否保
  • 对象锁定私有类成员 - 最佳实践? (爪哇)

    I asked 类似的问题 https stackoverflow com questions 10548066 multiple object locks in java前几天 但对回复不满意 主要是因为我提供的代码存在一些人们关注的问题
  • Java的-XX:+UseMembar参数是什么

    我在各种地方 论坛等 看到这个参数 并且常见的答案是它有助于高并发服务器 尽管如此 我还是找不到 sun 的官方文档来解释它的作用 另外 它是Java 6中添加的还是Java 5中存在的 顺便说一句 许多热点虚拟机参数的好地方是这一页 ht
  • 是否有一种更简单的方法可以并行运行命令,同时在 Windows PowerShell 中保持高效?

    此自我回答旨在为那些受困于 Windows PowerShell 并由于公司政策等原因而无法安装模块的用户提供一种简单且高效的并行替代方案 在 Windows PowerShell 中 built in可用的替代方案local并行调用是St
  • 在 .NET 并发线程之间传递数据的最佳方式是什么?

    我有两个线程 一个需要轮询一堆单独的静态资源以查找更新 另一种需要获取数据并将其存储在数据库中 线程1如何告诉线程2有东西要处理 如果数据块是独立的 则将数据块视为要由线程池处理的工作项 使用线程池和QueueUserWorkItem将数据
  • 将 ThreadLocal 与 ExecutorService 一起使用是否危险?

    我在下面的博客上介绍了 ThreadLocals 的概念 https www baeldung com java threadlocal https www baeldung com java threadlocal 它说 不要将 Thre
  • .NET 紧凑框架中的信号量

    不幸的是 使用 NET Compact Framework 时 System Threading 中没有信号量 我不确定为什么会这样 有人有想法吗 经过谷歌搜索后 我发现很多人给出了他们自己的实现 但他们中没有一个真正工作得很好 或者根本没
  • 确保 Clojure 中只有一个服务实例正在运行/启动/停止的规范方法?

    我正在用 Neo4j 支持的 Clojure 编写一个有状态服务器 它可以服务套接字请求 例如 HTTP 当然 这意味着我需要能够从该服务器内启动和停止套接字服务器 在设计方面 我希望能够在此服务器中声明一个 服务 并启动和停止它 我在 C
  • 冻结/挂起 tkinter GUI 等待线程完成

    按下按钮后我的界面冻结了 我正在使用线程 但我不确定为什么仍然挂起 任何帮助将不胜感激 提前致谢 class magic def init self self mainQueue queue Queue def addItem self q
  • 运行外部进程的非阻塞线程

    我创建了一个 Java GUI 应用程序 它充当许多低级外部进程的包装器 该实用程序按原样运行 但迫切需要一项重大改进 我希望我的外部进程以非阻塞方式运行 这将允许我并行服务其他请求 简而言之 我希望能够在生成数据时处理来自外部进程的数据
  • Play 框架:异步与同步性能

    我有以下代码 def sync Action val t0 System nanoTime Thread sleep 100 val t1 System nanoTime Ok Elapsed time t1 t0 1000000 0 ms
  • golang.org 包和标准库之间的区别

    我使用 go 已经有一段时间了 我注意到 Go 标准库 和 golang org x 之间存在重复的包 我的问题是 为什么它们被释放两次 在这两者中 我应该使用哪一个 更新的 规范的等 到目前为止我注意到的一些示例包已发布两次 golang
  • 从直方图计算平均值和百分位数?

    我编写了一个计时器 可以测量任何多线程应用程序中特定代码的性能 在下面的计时器中 它还会在地图中填充花费了 x 毫秒的调用次数 我将使用这张图作为我的直方图的一部分来进行进一步的分析 例如调用花费了这么多毫秒的百分比等等 public st
  • 单值上下文中的多值错误

    我在编译 GO 代码时遇到此错误 multiple value fmt Println in single value context 我正在尝试创建一个函数 该函数接受可变数量的整数并将每个变量打印在一行上 GO package main
  • GCD 与自定义队列

    我想知道这两者的性能有什么区别 dispatch async dispatch get global queue DISPATCH QUEUE PRIORITY HIGH 0 perform complex operation dispat

随机推荐

  • System.Data.OracleClient 不适用于 64 位 Oracle 客户端

    我设计了一个 C 应用程序来连接到 Oracle 数据库并更改架构用户密码 我的参考程序集是来自以下位置的 System Data OracleClient C Program Files x86 Reference Assemblies
  • Rails 4 中的 has_many 'conditions' 选项相当于什么?

    有人能告诉我在 Rails 4 中执行以下行的等效方法是什么吗 has many friends through gt friendships conditions gt status accepted order gt first nam
  • MSBuild - 如何复制可能存在或不存在的文件?

    我遇到一种情况 我需要在 MSBuild 脚本中复制一些特定文件 但它们可能存在也可能不存在 如果它们不存在也没关系 我就不需要它们了 但标准
  • 在未知的 NSMutableArray 深度中搜索值

    好吧 我问了错误的问题 所以我编辑了原来的问题 我将数组存储在数组中 以及 NSDictionaries 它是一种实用程序类型的应用程序 没有固定的结构 用户可以根据需要输入嵌套信息 理想情况下 我需要一种方法来滚动浏览给定参数 一种类的类
  • Cordova Android 状态栏设置为透明

    我正在尝试使用下面的这个插件将状态栏设置为透明 但我无法实现它 我可以将其更改为不同的颜色 但不透明 https github com apache cordova plugin statusbar https github com apa
  • 下载旧版本的 Google App Engine SDK

    在哪里可以找到下载旧版 GAE SDK 例如 1 9 15 我需要找出覆盖范围 也许使用第 3 方 API 该 API 与最新版本不能很好地配合 这取决于相应的 SDK 是否仍受官方支持 这两种类型都可以在appengine sdks ht
  • 使用文本框输入在画布上移动对象

    我有一个画布 可以在上面添加图层 这些图层可以移动 选择 旋转 调整大小等 在画布下方 我显示图层的属性 x y 宽度 高度 我想做的是 当我更改包含 x 和 y 坐标的文本框中的值时 图层应该重新定位到我输入的坐标 我已经尝试了几件事 但
  • 在 Windows 中更改 Python 3 中的“区域设置首选编码”

    我正在使用 Python 3 最近从 Python 2 切换而来 我的代码通常在 Linux 上运行 但有时 不经常 在 Windows 上运行 根据 Python 3 文档open https docs python org 3 libr
  • 以编程方式单击时突出显示 TextView

    我动态生成 TextView 其工作方式类似于按钮 现在我想在他们受到压力时突出显示他们 比如更改文本颜色或背景颜色 我尝试过使用选择器 但它不起作用
  • 如何设置 PowerShell Cmdlet 的默认输出格式?

    我正在 C 中创建一个 PowerShell Cmdlet 以从 JSON 文件读取字段并输出一些对象 这些对象是简单的 POCO 类型 public class FieldDefinition public FieldDefinition
  • C#动态编译字符串和.cs文件

    我正在开发一个网站 用户可以在该网站上针对浏览器文本区域中的问题实现 C 代码解决方案并提交 然后 服务器将将该代码与我在服务器上提供的预定义接口一起编译 将其视为一种策略设计模式 我提供一个策略接口 由用户实现 所以我需要在运行时一起编译
  • 部分排序数组,最后 n 个元素已排序?

    有没有办法对数据数组执行部分排序 以便对最后 n 个元素进行排序 我的意思是使用标准库 而不是实现我自己的排序函数 这就是我现在正在做的事情 示例输出 使用较少的比较器 2 1 4 5 6 8 10 之后的元素 都大于之前的元素 但仅限于右
  • 共享一个控制器的角度多条路线

    我不确定我是否正确处理了这个问题 但我正在构建一个电子商务网站 该网站的一部分有 6 个不同的产品网格页面 每个页面都可以使用相同的视图 ul class products row li class product thumbnail co
  • ASP.NET / Web.config:customErrors 仅在 404 上重定向

    我有这样的场景 用户访问我的网站并点击不再存在的链接 他应该被重定向到自定义错误页面 这样可行 如果用户执行某些操作 引发错误 他应该看到堆栈跟踪和真正的错误页面 这是我当前的 Web config
  • 使用 PHP 文件功能在另一台服务器上创建文件

    我的一台服务器上有一个脚本 我希望该脚本使用 PHP 在我的另一台服务器上创建一个文件 而不是通过 FTP 有很多方法可以做到这一点 我自己会选择第一个 因为它最容易设置 如果你有PHP 另一台服务器上的Apache 只需使用以下命令调用另
  • 将 pfx 格式转换为 p12

    我需要导出一个 pfx将证书格式 来自 Windows MMC 转换为 p12在另一个应用程序中使用 我找不到办法做到这一点 任何人都可以建议一个方法吗 p12 and pfx都是 PKCS 12 文件 我错过了什么吗 您是否尝试过重命名导
  • 从父子表生成字符串树分支

    我有一个父子表 如下所示 child father H G F G G D E D A E B C C E 我希望 sql server 生成类似的东西 正如这个问题中所问的那样 将一系列父子关系转化为层次树 https stackover
  • Angular 2.x 在 body 标签上绑定类

    由于 Angular 2 x 是在主体内部引导的 我该如何添加 class fixed isFixed 在 body 标签上 在我的应用程序之外
  • 匹配不带引号的逗号的正则表达式

    我正在使用 Clojure 所以这是在 Java 正则表达式的上下文中 这是一个示例字符串 a ab cd efg b ab def egf c Conjecture 重要的位是每个字符串后面的逗号 我希望能够使用Java的replaceA
  • Go 中的简单工作池

    我正在尝试在 go 中实现一个简单的工作池 但不断遇到问题 我想做的就是让一定数量的工人先完成一定数量的工作 然后再做更多的工作 我正在使用的代码类似于 jobs make chan imageMessage 1 results make