2015-10-17 68 views
0

我有一个服务调用数据库并对每个结果执行回调。执行器服务和巨大的IO

ExecutorService service = Executors.newFixedThreadPool(10); 
service.exectute(runnable(segmentID, callback)); // database is segmented 

Runnable的是:

call database - collect all the rows for the segment keep in memory 
perform callback(segment); 

现在的问题是,我得到数据库返回了一个庞大的行,我的理解是执行服务将调度线程,每当他们在I/O闲置。所以我进入了内存不足。

有什么办法可以限制只有10个线程在同一时间运行,并且没有执行器服务调度发生?

出于某种原因,我必须保持段中的所有行在内存中。 如何防止通过这样做去OOM。 Executor服务是否为此newFixedThreadPool解决方案?

请让我知道,如果我错过了什么。

谢谢

+1

处理未知事物的一些未知代码会导致内存问题。很难帮助。发布您的代码。告诉我们你如何“呼叫数据库”。向我们展示回调的功能。 –

+0

请假设我想在可运行内部执行大量的IO,并将检索到的值保存在内存中。如果我说10个线程在执行IO并且其他线程处于空闲状态,那么我不会去OOM,但是如果执行程序服务在执行IO时安排其他线程,那么我肯定会进入OOM。 –

+0

如果向10个线程可用的执行程序提交10个任务或更多任务,则10个线程*将*同时执行。这就是整个问题。如果你只想并行执行2个线程,那么用2个线程创建一个执行程序。但无论如何,即使任务完成后,所有内容都会保留在内存中,线程数量不会改变任何内容。 –

回答

1

您必须使用固定的线程池。有一条规则,你应该只产生N个线程,其中N应该与CPU的内核数量相同。关于N的大小有一个争论,你可以阅读更多关于它的文章here。对于一个普通的CPU,我们可以说4,8,16个线程。

但即使你在一个集群中运行你的程序,我认为你不是,你不能从数据库中取出20k行并假装产生20k个线程。如果这样做,应用程序的性能会降低大部分时间,因为大部分CPU周期将在上下文切换中消耗。

现在,即使使用固定线程池,如果获取的数据同时存储在内存中,也可能会遇到OOM异常。我认为唯一的解决方案是获取更小的数据块,或者在数据下载时将数据写入文件。

+0

感谢:) –