首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >服务器上的多线程应用程序比单线程慢(与JUnit测试不同)

服务器上的多线程应用程序比单线程慢(与JUnit测试不同)
EN

Stack Overflow用户
提问于 2011-04-08 11:11:29
回答 3查看 1.1K关注 0票数 0

我已经将我的应用程序从一个单线程切换到一个多线程例程。

这在JUnit测试中非常好。当使用10线程运行它时,测试需要195 ms来完成,当只使用一个线程运行它时,应用程序需要406 ms来完成。因此,显然有一个性能优势。

但是,当它在服务器上运行时,应用程序现在所需的时间要比只有单线程时长得多。

基本上,我的应用程序读取csv文件中的一行,将它的一个值放在一个集合中,并将该行打印到另一个文件中。JUnit测试中输入文件的大小是关于35行长的,服务器上的输入文件大小是6 000 000行长的。

放置这些值的集合是一个同步的HashSet,它可以包含Long对象。

我正在使用Java VisualVM监视我的应用程序,但不幸的是,我不知道该寻找什么。

你对我如何解决这场表演危机有什么建议吗?

P.S.:大多数时候,我的线程被标记为等待,但我不知道它们是否真的在等待,或者它们是否太快,以致于Java VisualVM无法显示它。

为了进一步澄清我的例程:我读取了单线程文件,但是一旦读取了行,我就将结果对象传递给一个Runnable,该对象将其放入一个集合并打印到另一个文件中。同时,读取下一行并将其传递给其他线程。

正如我在日志文件中所看到的那样,线程正在做一些事情,而不仅仅是等待。但也有某些跳跃,比100毫秒更长的时间,在那里什么都没有发生。

其中一次跳跃:

代码语言:javascript
复制
2011-04-08 12:27:16,580 DEBUG [Thread-10]  runnables.Runner - 7070927
2011-04-08 12:27:16,580 DEBUG [Thread-10]  runnables.Runner - 9058759
2011-04-08 12:27:16,580 DEBUG [Thread-10]  runnables.Runner - 7030928
2011-04-08 12:27:16,580 DEBUG [Thread-10]  runnables.Runner - 15301035
2011-04-08 12:27:16,684 DEBUG [Thread-10]  runnables.Runner - 7700929
2011-04-08 12:27:16,684 DEBUG [Thread-10]  runnables.Runner - 17116545
2011-04-08 12:27:16,685 DEBUG [Thread-10]  runnables.Runner - 4933581
2011-04-08 12:27:16,685 DEBUG [Thread-10]  runnables.Runner - 2861116

注:当时没有发生GC。

正如在下面的注释中所写的:我正在使用线程池。我的线程正在为同一个输出文件而斗争。它们都写入synchronized方法。

即使我把我的踏面池缩小到一个,表现还是很糟糕的。与以前的实现相比没有什么。这难道不排除IO依赖或线程切换之类的东西吗?

我现在已经修改了我的代码,以便在Runnable中几乎什么都不做。没有Set,没有写作。只有一条日志语句。但我还是得到了那些jumps。因此,我排除了一些人提出的写作或Set问题。当只运行一个线程时,我也得到了这些空闲时间。因此,线程滑动似乎也不是问题所在。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-04-08 13:27:12

我不知道具体的问题是什么,但它似乎是由Executor接口的一个糟糕的实现引起的。

我现在用

代码语言:javascript
复制
ExecutorService executor = Executors.newFixedThreadPool(nThreads);

一切都很好。

  • 单线程例程持续时间:17.12 min
  • 持续时间10线程例程:13.45 min

我发现了坏的代码:

代码语言:javascript
复制
Thread.sleep(100);

在线程队列已满时调用。

票数 0
EN

Stack Overflow用户

发布于 2011-04-08 11:23:22

您的测试文件非常小,因此它很可能被整个I/O堆栈中的任何预读层完全读取。这使得整个执行CPU绑定。有了更多的线程,就可以使用更多的CPU并使其完成得更快。

真正的文件OTOH要长得多,所以问题变成了IO绑定。CPU大部分时间都在等待读取数据。在单个线程上,没有争用,IO可能更线性;而多线程版本更有可能生成大量的磁盘查找(到目前为止,在硬件上所能做的最慢的操作)

根据经验,如果您从磁盘或网络读取数据,并且不对其进行大量处理,则最好采用单线程处理。

票数 7
EN

Stack Overflow用户

发布于 2011-04-08 11:30:01

您所指的“跳转”是线程之间的切换时间。由于总的执行时间是有限的,一个线程的执行时间就会变得越小,您拥有的线程就越多。如果您必须执行多个线程,那么您的调度程序最终会切换线程,而没有线程会执行任何工作。从一个线程切换到另一个线程需要一定的固定时间。如果您的线程不使用多个内核,并且执行完全相同的操作,那么当比较多线程和单线程时,您的速度会更快。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5594227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档