2

我正在使用Spring Batch并使用ThreadPoolTask​​Executor来分叉多个线程。 文件很大,像175 MB,我正在处理大量的字符串对象。 由于此OutOfMemory错误正在抛出。在Spring批处理ThreadPoolTask​​Executor引用不被垃圾收集

下面的配置将调用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后,我做的很多模式匹配的处理器。

+0

你的块大小有多大?而且,多线程读取文件通常不会通过性能获得太多好处。 –

+0

您的内存泄漏不在您发布的代码中。您应该发布实际的I/O代码或使用散列映射的代码。我的第一个猜测是你没有关闭将文件读入内存的流。 – ngreen

+0

我刚刚编辑了我的问题来掩盖以上问题。 – Ramandeep

回答

1

为了解决这个问题,你可能必须用Eclipse MAT或其他一些工具来分析jmap dunp文件。由于问题可能与代码的每个细节都有关系。

我只是在这里给出一个可能的原因:ExecutorService有一个BlockingQueue用于等待作业,这些等待作业也保留内存。因此,如果提交作业过快,很容易出现内存不足。

+0

它似乎并非如此,我也试过睡眠方法,以减缓执行。 – Ramandeep