Clojure:创建和管理多个线程

时间:2017-05-17 15:02:06

标签: multithreading clojure

我编写了一个程序,需要处理一个非常大的数据集,我打算在高端机器上运行多个线程。

我是Clojure的初学者,我迷失在无数的工具中 -  agent,futures,core.async(和Quartzite?)。我想知道哪一个最适合这份工作。

以下描述了我的情况:

  1. 我有一个函数可以转换一些数据并将其存储在数据库中。
  2. 该函数的参数从Redis集中弹出。
  3. 只要Redis集中有值,就可以在几个单独的线程中运行该函数。

3 个答案:

答案 0 :(得分:3)

为简单起见,期货无法被击败。他们创建一个新线程,并从中返回一个值。但是,通常需要比他们提供的更细粒度的控制。

core.async库对并行性有很好的支持(通过管道,见下文),它还提供自动背压。你必须有一种方法来控制数据流,这样就不会有人为工作而挨饿,也不会有太多的负担。 core.async频道必须有界限,这有助于解决这个问题。此外,它是您的问题的一个非常合理的模型:从一个来源获取一个值,使用某个给定的transducer转换它(可能使用parallelism?),然后将结果输入到您的数据库中。

您还可以使用Java优秀的j.u.concurrent库的手动路线。 thread management有低级原语和thread pools工具。所有这些都可以在clojure中使用。

从设计的角度来看,它取决于您是更多的CPU绑定还是I / O绑定。这会影响决策,例如您是否将从redis执行并行读取以及写入数据库。如果你受CPU限制,因此你的瓶颈就是计算,那么从redis并行读取你的读取或者你的数据库写入是不是很有意义呢?这些是要考虑的事情类型。

你真的有两个问题要解决:(1)你熟悉clojure&java的并发机制,以及(2)你对这个问题的处理方法(即你如何处理这个问题,不论你使用的语言是什么?)。一旦你解决了#2,你就会更好地了解我上面提到的使用哪些工具,以及如何使用它们。

答案 1 :(得分:1)

听起来你可能有 好 embarrassingly parallel问题 解决。在这种情况下,你可以简单地开始编码你的 处理成处理第一个数据的顶级函数。 一旦它正常工作,请将其包装好 一个map处理所有的 数据顺序(连续,一次一个)。

您可能只想开始解决更大的问题 数据集中的项目。这将使您的测试更顺畅 更快。

map工作后,现在只需添加p (并行)代码来实现它 一个pmap。这是非常的 有益的方式来加热你的 机。 Here是 关于pmap使用的线程数的讨论。

以上是最简单的方法。如果你需要更好的控制权 并发, this concurrency screencast探讨 用例。

答案 2 :(得分:1)

很难准确无需了解问题的详细信息。你提到有几种选择:

  • 普通Java线程&线程池。如果您的问题类似于预先存在的Java解决方案,那么这可能是最直接的。
  • 简单的Clojure线程与future等。用future开始一个帖子并将结果放在promise中非常容易。
  • map替换为pmap(并行地图)。这可以帮助处理主要是map / reduce的简单情况。
  • Claypoole库:许多工具使多线程更简单,更容易。请参阅their GitHub projectClojure/West talk.