Java 在Spring中,批处理ThreadPoolTaskExecutor引用不会被垃圾收集

Java 在Spring中,批处理ThreadPoolTaskExecutor引用不会被垃圾收集,java,multithreading,out-of-memory,spring-batch,threadpoolexecutor,Java,Multithreading,Out Of Memory,Spring Batch,Threadpoolexecutor,我正在处理Spring批处理,并使用ThreadPoolTaskExecutor来分叉多个线程。 这些文件很大,比如175MB,我处理的是很多字符串对象。 由于此OutOfMemory错误被抛出 下面的配置将调用1个线程来处理1个文件(customDBPartitioner正在拾取文件) 以下是配置: <bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTa

我正在处理Spring批处理,并使用ThreadPoolTaskExecutor来分叉多个线程。 这些文件很大,比如175MB,我处理的是很多字符串对象。 由于此OutOfMemory错误被抛出

下面的配置将调用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(preprocessutil.getAvailableMemory()

我尝试的是,如果没有足够的内存,那么不要执行处理下一个文件的步骤

当可用内存低于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文件=新的StringBuilder()
试一试{
//我也试过这个。
//append(FileUtils.readFileToString(resource.getFile());
logger.info(“文件大小:“+resource.getFilename()+”为“+FileUtils.sizeOf(resource.getFile())/1024+”KB”);
已同步(UnixFileItemReader.class){
lineIterator=FileUtils.lineIterator(resource.getFile());
/*while(preprocessutil.getAvailableMemoryNoLogs()

在StringBuilder中读取整个文件后,我在处理器中进行了大量的模式匹配。

要解决这个问题,最后可能需要使用Eclipse MAT或其他工具分析jmap dunp文件。因为问题可能与代码的每个细节都有关系


这里我只给出一个可能的原因:ExecutorService有一个用于等待作业的阻塞队列,这些等待作业还保留内存。因此,如果提交作业太快,很容易内存不足。

块大小有多大?此外,多线程读取文件通常不会从性能上获得太多好处。您发布的代码中没有内存泄漏。您应该发布实际的I/O代码或使用哈希映射的代码。我的第一个猜测是,您没有关闭正在将文件读入内存的流。我只是编辑了我的问题以掩盖上述问题。情况似乎并非如此,我还尝试了sleep方法来降低执行速度。