我正在使用Spring Batch并使用ThreadPoolTaskExecutor来分叉多个线程。 文件很大,像175 MB,我正在处理大量的字符串对象。 由于此OutOfMemory错误正在抛出。在Spring批处理ThreadPoolTaskExecutor引用不被垃圾收集
下面的配置将调用1个线程来处理1个文件(customDBPartitioner正在拾取文件)。
下面是配置:
<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="3" />
<property name="maxPoolSize" value="3" />
</bean>
<step id="unixPartitionerStep">
<partition step="unixItemStep" partitioner="customDBPartitioner">
<handler grid-size="10" task-executor="threadPoolTaskExecutor" />
</partition>
</step>
<listeners>
<listener ref="unixJobListener" />
</listeners>
所以当这一步被调用:3个线程开始处理文件,以保持检查记忆我已经把stepListener的条件。
while(preProcessorUtil.getAvailableMemory() < minimumMemoryRequired) { logger.info("Thread going to sleep as memory is not enough - " + inputFile.getFilename()); Thread.sleep(5000); }
我试图是如果有足够的内存不可用,则不去执行,用于处理下一个文件的步骤。
在可用内存低于memoryRequired之后,线程进入睡眠模式,但GC永远不会被调用,而是内存持续减少。
有人可以请帮助,让我知道这里有什么问题,如何回收内存来处理文件?
编辑: 在JvisualVM,最大内存采取的是字符串/字符
块大小为1 那就是:我要求每个线程在同一时间读取一个文件/工作。文件大小从KB到100 MB不等。 我不能选择一个选项来逐行处理文件,因为在处理
我必须引用文件中的不同部分。 下面是从阅读器的代码,它读取一个文件中的一个块
StringBuilder file = new StringBuilder()
try {
// I tried this as well.
//file.append(FileUtils.readFileToString(resource.getFile()));
logger.info("Size of file : "+ resource.getFilename() +" is " + FileUtils.sizeOf(resource.getFile())/1024 + " KB");
synchronized(UnixFileItemReader.class) {
lineIterator = FileUtils.lineIterator(resource.getFile());
/*while(PreProcessorUtil.getAvailableMemoryNoLogs() < minimumMemoryRequired) {
Thread.sleep(5000);
}*/
while (lineIterator.hasNext()) {
file.append(lineIterator.nextLine()).append("\r\n");
}
}
} catch(Exception ex) {
ex.printStackTrace();
file = null;
throw ex;
} finally {
LineIterator.closeQuietly(lineIterator);
}
读取整个文件中的一个StringBuilder后,我做的很多模式匹配的处理器。
你的块大小有多大?而且,多线程读取文件通常不会通过性能获得太多好处。 –
您的内存泄漏不在您发布的代码中。您应该发布实际的I/O代码或使用散列映射的代码。我的第一个猜测是你没有关闭将文件读入内存的流。 – ngreen
我刚刚编辑了我的问题来掩盖以上问题。 – Ramandeep