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