Executor 服务和巨大的 IO
Executor Service and Huge IO
我有一个调用数据库并对每个结果执行回调的服务。
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 service newFixedThreadPool 解决这个问题吗?
如果我遗漏了什么,请告诉我。
谢谢
您必须使用固定的线程池。有一个规则,你应该只产生 N 个线程,其中 N 应该与 CPU 中的核心数量处于相同的数量级。关于 N 的大小存在争议,您可以阅读更多相关内容 here。对于正常的 CPU,我们可以谈论 4,8,16 个线程。
但是,即使您 运行 在集群中部署您的程序(我认为您不是),您也不能只从数据库中获取 20k 行并假装生成 20k 线程。如果这样做,您的应用程序的性能将会大幅下降,因为大部分 CPU 周期将用于上下文切换。
现在即使使用固定线程池,如果获取的数据同时存储在内存中,您也可能 运行 出现 OOM 异常。我认为唯一的解决方案是获取更小的数据块,或者在下载数据时将数据写入文件。
我有一个调用数据库并对每个结果执行回调的服务。
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 service newFixedThreadPool 解决这个问题吗?
如果我遗漏了什么,请告诉我。
谢谢
您必须使用固定的线程池。有一个规则,你应该只产生 N 个线程,其中 N 应该与 CPU 中的核心数量处于相同的数量级。关于 N 的大小存在争议,您可以阅读更多相关内容 here。对于正常的 CPU,我们可以谈论 4,8,16 个线程。
但是,即使您 运行 在集群中部署您的程序(我认为您不是),您也不能只从数据库中获取 20k 行并假装生成 20k 线程。如果这样做,您的应用程序的性能将会大幅下降,因为大部分 CPU 周期将用于上下文切换。
现在即使使用固定线程池,如果获取的数据同时存储在内存中,您也可能 运行 出现 OOM 异常。我认为唯一的解决方案是获取更小的数据块,或者在下载数据时将数据写入文件。