2012-07-28 264 views
7

我正处于一个问题中,我无法决定采取哪种解决方案。线程池vs许多单线程

这个问题有点独特。让我们这样说,我从网络上不断接收数据(每秒2到4次)。现在每个数据都属于不同的组,比如说。 现在,我们称这些组,group1,group2等。

每个组都有一个专门的作业队列,来自网络的数据将被过滤并添加到其相应的组中进行处理。

起初,我为每个组创建了一个专用线程,它将从作业队列获取数据,对其进行处理,然后进入阻塞状态(使用链接阻塞队列)。

但是我的高级建议我应该使用线程池,因为这种方式线程不会被阻塞,并且可以被其他组用于处理。

但是,事情就是这样,数据即时获取速度足够快,并且线程处理它的时间足以让线程可能不会进入阻塞模式。这也将保证数据按顺序进行处理(作业1在作业2之前完成),这在池中很少有机会可能不会发生。

我的老人也倾向于这样的事实,因为线程是POOLED(即时通讯认为他真的是这个词;)),汇集也将节省我们大量的内存。虽然我不同意这一点,因为我个人认为,汇集或不是每个线程都有自己的堆栈内存。除非线程池中有某些我不知道的东西。

最后一件事,我一直认为集合有助于短时间内在大量工作中出现工作。这是有道理的,因为线程产生将是一个性能杀手,因为初始化一个线程所花费的时间比做这项工作花费的时间多得多。所以在这里汇集有很多帮助。

但在我的情况下,group1,group2,...,groupN总是保持活着。所以如果有数据,他们仍然会在那里。所以线程产卵在这里不是问题。

我的老人不服气,希望我使用pooling解决方案,因为它的内存占用很大。

那么,采取哪条路?

谢谢。

+0

在这样的情况下,只有一个答案。冷酷的事实!通过适当的受控模型/原型证明哪个更好。您可能会感到惊讶,因为在不同的情况下,每个人都可能有效。 – 2012-07-28 11:59:18

+0

需要CYA备忘录 - 通过电子邮件详细说明您的问题/疑虑,然后按照老年人的建议使用合并解决方案。如果集中设计存在问题,则屏蔽:)。看看你的需求,我可能会用一组专用的线程 - 这些线程只在启动时创建,并且一个线程比一个异步的状态引擎更容易调试,而这个状态引擎必须在需要做的事情时不断发布到池中。如果线程池没有使用异步方法,则任何阻塞调用都会阻塞池线程,从而迫使系统创建更多线程:( – 2012-07-28 12:42:25

+0

如果您的应用程序为每个组创建一个线程,并且每个线程从自己的队列中获取数据,并且无限地运行,你实际上拥有一个固定的线程池,创建一个具有相同线程数量的“真实”线程池不会有太大的改变,使用“真实”线程池可以获得的好处是只需少量线程从所有队列中选择数据,并且如果线程池队列中等待的任务太多,或者线程太多,空闲线程池可能会根据需要增长和缩小。 – 2012-07-28 13:24:53

回答

2

好问题。如您所说,共享池确实可以节省您的初始化时间。但它有另一个方面:资源管理。在这里,我问你这个 - 你有多少组(专用线程)? 它们是否在应用程序的执行期间动态增长?

例如,考虑这个问题的答案是肯定的情况。动态添加新的组类型。在这种情况下,您可能不希望为每个线程分配一个线程,因为技术上对将要创建的组的数量没有限制,您将创建大量线程,并且系统将进行上下文切换而不是实际工作。 线程到救援线程池允许您指定对最大线程数的限制,该线程数可能是可能是创建的,不考虑负载。因此,应用程序可能会拒绝来自某些请求的服务,但是那些能够正确处理的请求不会严重耗尽系统资源。

考虑到上述情况,我很可能在您的情况下,为每个组设置专用的 线程是非常可行的!

对于老人的信念,它会节省内存也是一样。事实上,一个线程在堆上占用内存,但是它真的非常多,如果它是预定义的数量,比如说5。可能是好的。无论如何,除非你是优先考虑的,并且绝对相信你确实有问题,否则你不应该使用集合。

池是一个设计决定,而不是建筑设计。您无法在开始时集中注意力,并在遇到后遇到性能问题时,继续进行优化,以便在发现合并带来收益时

考虑到请求的序列化(按顺序执行),不管你使用的是线程池还是专用线程。顺序执行是与单个处理程序线程耦合的队列的属性。

+0

感谢您的答复。至于动态组创建,不会动态创建组。但是有很多团体,大约15-20。预计它们会增加,但它们将在开始时被创建和设置。现在执行顺序是一个问题,在这种情况下,合并可能很难实现。但你没有清楚地告诉我,池中的线程比没有池的线程需要的内存少。谢谢。 – 2012-07-28 12:25:54

+1

池中的线程与其他线程完全相同。他们消耗相同数量的内存。使用池的好处是它可以避免不断创建和删除线程,并且可以将并发线程的数量保持为固定的或合理的数量。 – 2012-07-28 13:41:08

+2

正如@JBNizet所说,线程池中的线程是相同的线程。只有另一种机制负责他们的一生。线程池中的线程*不会占用比常规线程少的内存。 请考虑以下内容: 由于您拥有的团队相对较多,因此我可以谨慎地断定您可能会更适合使用线程池:正如我之前所提到的,从资源管理的角度来看,如果您拥有比核心更多的线程来运行它们(并且你的逻辑主要是CPU绑定的),你将花费很多时间在ctx切换。再一次,需要彻底的性能测试! – Vitaliy 2012-07-28 17:01:04

3

创建线程将消耗资源,包括每个线程的默认堆栈(IIR 512Kb,但可配置)。因此,合并的好处是您会受到有限的资源冲击。当然,您需要根据您必须执行的工作来调整游泳池的大小。

对于您的特定问题,我认为关键是在每种情况下实际衡量性能/线程使用情况等。除非遇到约束,否则我可能不会担心任何其他方式,除非确保您可以将一个实现替换为另一个实现,而不会对应用程序产生重大影响。请记住,不成熟的优化是所有邪恶的根源Note that

“过早优化”是用来描述一种情况 其中一个程序员可以让性能因素影响的一段代码的设计 的短语。这可能导致设计不像原来那样清洁 或代码不正确,因为代码是 因优化而变得复杂,程序员被 优化分心。

+0

因此,池中的线程使用的内存少于单个内存,这是正确的吗?另外,pooling实现导致了另一个问题,即序列跳过,以前启动的线程有时会花费更多的时间,导致另一个线程在稍后开始完成。周围有什么? – 2012-07-28 12:11:52

+0

序列号和一个'resequencer'类/线程,用于保存无序输出的列表/队列,直到所有更早的进来。 – 2012-07-28 12:48:19