我有一个服务调用数据库并对每个结果执行回调。
ExecutorService service = Executors.newFixedThreadPool(10);
service.exectute(runnable(segmentID, callback)); // database is segmented
可运行的是:
call database - collect all the rows for the segment keep in memory
perform callback(segment);
现在的问题是我收到数据库返回的大量行,我的理解是执行器服务将在 I/O 空闲时调度线程。所以我进入了“内存不足”状态。
有没有办法限制一次只运行10个线程,并且不发生执行器服务调度?
出于某种原因,我必须将段的所有行保留在内存中。 我怎样才能通过这样做来防止 OOM。 Executor 服务 newFixedThreadPool 是否可以解决此问题?
如果我错过了什么,请告诉我。
谢谢
最佳答案
您必须使用固定线程池。有一条规则,您应该只生成 N 个线程,其中 N 的数量级应该与 CPU 中的核心数量相同。关于 N 的大小存在争议,您可以阅读更多相关内容 here 。对于普通 CPU,我们可以讨论 4、8、16 个线程。
但是,即使您在集群中运行程序(我认为您不是),您也不能只从数据库中获取 20k 行并假装生成 20k 线程。如果这样做,应用程序的性能将会大幅下降,因为大部分 CPU 周期将消耗在上下文切换中。
现在,即使使用固定的线程池,如果获取的数据同时存储在内存中,您也可能会遇到 OOM 异常。我认为唯一的解决方案是获取较小的数据 block ,或者在下载数据时将数据写入文件。
关于java - 执行器服务和巨大的IO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33186187/