【发布时间】:2011-04-08 11:11:29
【问题描述】:
我已将我的应用程序从单线程例程切换到多线程例程。
这在 JUnit 测试中工作得很好。当使用10 线程运行它时,测试需要195 ms 才能完成,而当仅使用一个线程运行它时,应用程序需要406 ms 才能完成。所以显然有性能优势。
但是当在服务器上运行它时,应用程序现在需要比单线程时更长的时间。
基本上,我的应用程序读取 csv 文件中的一行,将其中一个值放入一个集合中,然后将该行打印到另一个文件中。
JUnit 测试中输入文件的大小约为35 行长,服务器上的文件大小约为6 000 000 行长。
放置这些值的集合是一个同步的HashSet,它可以包含Long 对象。
我正在使用 Java VisualVM 监控我的应用程序,但不幸的是我不知道要查找什么。
你对如何解决这个性能危机有什么建议吗?
P。 S.:大多数时候我的线程被标记为等待,但我不知道它们是否真的在等待,或者它们是否太快以至于 Java VisualVM 无法显示它。
为了进一步阐明我的例程:我单线程读取文件,但是一旦读取该行,我就会将生成的对象传递给 Runnable,将其放入一个集合中并将其打印到另一个文件中。同时读取下一行并将其传递给其他线程。
正如我在日志文件中看到的那样,线程正在做某事,而不仅仅是等待。但是有某些跳跃,比100 ms 更长的时间段没有发生任何事情。
其中一个跳跃:
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问题。当只运行一个线程时,我也得到了这些空闲时间。所以线程切换似乎也不是问题。
【问题讨论】:
-
您是否尝试过使用长文件运行单元测试?另外,目前还不清楚如何通过多线程读取文件。
-
感谢您的提示。在问题底部查看我的更新。
-
可能需要查看一些代码来帮助诊断这个。
-
可能同步读取/写入文件和设置哈希集比没有它的一个线程完成的相同工作需要更长的时间。您的单元测试可能效果更好,因为输入/输出文件很小并且由操作系统缓存。
-
您是使用一种线程池形式还是最终拥有 600 万个线程? thr 线程是否还会尝试将内容写入相同的输出文件或不同的输出文件(即它们是否在争夺该资源?)
标签: java multithreading performance debugging