Java线程在处理结束时变慢
作者:互联网
我有一个Java程序,它接收一个包含文本文件列表的文本文件,并分别处理每一行.为了加快处理速度,我使用带有24个线程的FixedThreadPool的ExecutorService来使用线程.该机器有24个内核和48GB内存.
我正在处理的文本文件有250万行.我发现,对于前230万行左右,在CPU利用率很高的情况下运行良好.然而,超过某些点(大约在2.3行),性能退化,只使用了一个CPU,我的程序几乎停止了.
我调查了很多原因,确保关闭所有文件句柄,并增加提供给JVM的内存量.但是,无论我改变什么,性能总是会降低到最后.我甚至尝试过包含更少行的文本文件,并且在处理文件结束时性能再次下降.
除了标准的Java并发库之外,代码还使用Lucene库进行文本处理和分析.
当我没有线程化这个代码时,性能是不变的,并且不会在最后退化.我知道这是一个黑暗的镜头,很难描述发生了什么,但我想我会看到是否有人有任何想法可能会导致这种性能退化到底.
编辑
在我收到的评论之后,我已经粘贴了一个堆栈跟踪here.正如您所看到的,它似乎没有任何线程阻塞.此外,在分析时,当事情变慢时,GC不是100%.实际上,CPU和GC的利用率在大多数情况下都是0%,CPU会偶尔处理一些文件,然后再次停止.
执行线程的代码
BufferedReader read = new BufferedReader(new FileReader(inputFile));
ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
String line;
while ((line = read.readLine()) != null) { //index each line
Runnable worker = new CharikarHashThreader(line, bits, minTokens);
executor.execute(worker);
}
read.close();
解决方法:
这听起来很像垃圾收集/内存问题.
当垃圾收集运行时,它会暂停所有线程,以便GC线程可以执行其“可收集的垃圾”分析,而不会对其进行任何更改.当GC运行时,您将看到100%的正好1个线程,其他线程将停留在0%.
我会考虑添加一些Runtime.freeMemory()调用(或使用分析器)来查看在GC期间是否“发生停顿”.
我还尝试在你的文件的前10k行运行你的程序,看看是否有效.
我还要看看你的程序是否在使用StringBuilders时构建了太多的中间字符串.
听起来像你需要描述你的内存使用情况.
标签:java,multithreading,lucene,java-util-concurrent 来源: https://codeday.me/bug/20190703/1370254.html