java - 在 Spring Batch 中,ThreadPoolTask​​Executor 引用不会被垃圾回收

标签 java multithreading out-of-memory spring-batch threadpoolexecutor

我正在使用 Spring Batch 并使用 ThreadPoolTask​​Executor 来创建多个线程。 这些文件很大,大约 175 MB,我正在处理很多字符串对象。 由于此 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(preProcessorUtil.getAvailableMemory() < minimumMemoryRequired) { logger.info("Thread going to sleep as memory is not enough - " + inputFile.getFilename()); Thread.sleep(5000); }

我正在尝试的是如果没有足够的内存可用则不要执行处理下一个文件的步骤。

可用内存低于 memoryRequired 后,线程进入 hibernate 模式,但 GC 永远不会被调用,内存会继续减少。

有人可以帮忙告诉我这里的问题是什么,如何回收内存来处理文件?

编辑: 在 JvisualVM 中,大部分内存被 Strings/chars 占用

block 大小为 1 那就是:我要求每个线程一次读取/处理一个文件。文件大小从 KB 到 100 MB 不等。 我无法选择逐行处理文件的选项,因为在处理时
我必须引用文件中的不同部分。 这是 Reader 的代码,它正在读取一个 block 中的一个文件

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 中读取整个文件后,我在处理器中进行大量模式匹配。

最佳答案

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

这里我只是给出一个可能的原因:ExecutorService有一个BlockingQueue用于等待作业,这些等待作业也是保持内存的。所以如果提交作业的速度太快,很容易出现内存不足的情况。

关于java - 在 Spring Batch 中,ThreadPoolTask​​Executor 引用不会被垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44297715/

相关文章:

java - 一个JVM可以获取两个共享文件锁吗?

java - Linux 上的多个 Java webapps 总线程限制

java - 如何在正则表达式中匹配包含 3 个或更多数字的单词?

java - JTable 中未显示 ColumnName

java - 如何使用 Selenium Java 查找表中元素的行索引

java - AerospikeException - 错误代码 1500 : LDT-Not Enabled on Namespace on lmap. put(),即使 ldt-enabled 设置为 true

python - 一起使用模拟 (MyHDL) 和 wxPython

c# - System.Data.SQLite for .NET 中的序列化模式

php - apache httpd 耗尽内存直到挂起

java - 如何在没有内存问题的情况下使用 REST 模板 Spring MVC 获取大型 JSON