我们使用 JDK 7 watchservice 来监视可以包含 xml 或 csv 文件的目录。这些文件被放入线程池中,然后被处理并推送到数据库中。这个应用程序永远运行,观察目录,并在可用时保持处理文件。XML 文件很小,不需要时间,但是每个 csv 文件可以包含超过 80,000 条记录,因此处理需要时间才能放入数据库。当从线程池处理 15 个 csv 文件时,Java 应用程序会出现内存不足错误。当csv文件进入线程池时,有什么方法可以串行处理,即一次只能处理一个。
问问题
1127 次
3 回答
1
当从线程池处理 15 个 csv 文件时,Java 应用程序会出现内存不足错误。当csv文件进入线程池时,有什么方法可以串行处理,即一次只能处理一个。
如果我理解,如果您超过某个阈值,您想停止添加到池中。有一种简单的方法可以做到这一点,即使用阻塞队列和被拒绝的执行处理程序。
请参阅以下答案:
总而言之,您可以执行以下操作:
// only allow 100 jobs to queue
final BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(100);
ThreadPoolExecutor threadPool =
new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, queue);
// we need our RejectedExecutionHandler to block if the queue is full
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
// this will block the producer until there's room in the queue
executor.getQueue().put(r);
} catch (InterruptedException e) {
throw new RejectedExecutionException(
"Unexpected InterruptedException", e);
}
}
});
这意味着它将阻止添加到队列中并且不应该耗尽内存。
于 2013-09-05T18:34:31.863 回答
1
我会采取不同的方法来解决您的问题,我想您一切正常,除非您开始将太多数据读入内存。
不确定你是如何读取 csv 文件的,建议使用 LineReader 并读取例如 500 行处理它们然后读取接下来的 500 行,所有大文件都应该只以这种方式处理,因为无论你增加多少内存参数,一旦你有一个更大的文件要处理,你就会内存不足,所以使用一个可以批量处理记录的实现。这将需要一些额外的编码工作,但无论您必须处理多大的文件,都不会失败。
干杯!!
于 2013-09-05T20:07:42.407 回答
0
你可以试试:
-Xmx
使用JVM 选项增加 JVM 的内存使用不同的执行器一次减少处理的文件数。一个激进的解决方案是使用
SingleThreadExecutor
:public class FileProcessor implements Runnable { public FileProcessor(String name) { } public void run() { // process file } } // ... ExecutorService executor = Executors.newSingleThreadExecutor(); // ... public void onNewFile(String fileName) { executor.submit(new FileProcessor(fileName)); }
于 2013-09-05T18:00:16.523 回答