我使用forPool = Executors.newFixedThreadPool(poolSize)创建一个固定的线程池;其中poolSize初始化为处理器上的核心数(假设为4).在某些运行中,它运行正常,CPU利用率始终为400%.
但有时,使用量下降到100%,并且从未上升到400%.我预定了1000个任务,所以问题不是这样.我捕获每个异常,但没有抛出任何异常.所以这个问题是随机的,不可重现,但非常存在.它们是数据并行操作.在每个线程的末尾,都有一个同步访问来更新单个变量.我不太可能在那里遇到僵局.事实上,一旦我发现了这个问题,如果我破坏游泳池,并创建一个4号的新游戏,它仍然只有100%的使用率.没有I / O.
这似乎与java对“FixedThreadPool”的保证相反.我读错了吗?只保证并发性而不是并行性?
对于这个问题 – 您是否遇到过这个问题并解决了它?如果我想要并行,我做的是正确的吗?
谢谢!
在做一个线程转储:
我发现有4个线程都在进行并行操作.但用量仍然只有100%左右.以下是400% usage和100% usage处的线程转储.我将线程数设置为16以触发方案.它运行400%一段时间,然后下降到100%.当我使用4个线程时,它运行400%,很少下降到100%. This是并行化代码.
****** [MAJOR UPDATE] ******
事实证明,如果我给JVM提供了大量的内存,这个问题就解决了,性能也没有下降.但我不知道如何使用这些信息来解决这个问题.救命!
解决方法:
鉴于增加堆大小会使问题“消失”(可能不是永久性的),问题可能与GC有关.
操作实现是否可能在调用之间生成一些存储在堆上的状态
pOperation.perform(...);
?如果是这样,那么您可能会遇到内存使用问题,可能是泄漏问题.随着更多任务的完成,堆上会有更多数据.垃圾收集器必须尽可能多地努力尝试和回收,逐渐占用总可用CPU资源的75%.即使破坏ThreadPool也无济于事,因为那不是存储引用的地方,而是在操作中.
解决这个问题的16线程案例更多可能是因为它更快地生成更多状态(不知道操作实现,所以我很难说).
并且在保持问题设置相同的同时增加堆大小会使这个问题看起来消失,因为你有足够的空间来处理所有这些状态.