Java Thread.sleep是否减少了读取和保存大文件时的内存问题

Java Thread.sleep是否减少了读取和保存大文件时的内存问题,java,multithreading,spring,jpa,spring-data,Java,Multithreading,Spring,Jpa,Spring Data,我将实用程序类作为java应用程序运行。该类读取一个包含500万条记录的csv文件,并尝试在数据库中保存大约125k条记录。中途我得到了堆空间错误。完整文件运行大约需要5-6小时。添加thread.sleep方法是否有助于清理作为java应用程序运行的资源?我使用spring数据jpa在每1k行之后插入 String strLine; List<Provider> providers = new ArrayList<Provider>(); in

我将实用程序类作为java应用程序运行。该类读取一个包含500万条记录的csv文件,并尝试在数据库中保存大约125k条记录。中途我得到了堆空间错误。完整文件运行大约需要5-6小时。添加thread.sleep方法是否有助于清理作为java应用程序运行的资源?我使用spring数据jpa在每1k行之后插入

    String strLine;
    List<Provider> providers = new ArrayList<Provider>();

    int count = 0;
    while ((strLine = br.readLine()) != null) {
      String[] providerDetails = strLine.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
      if (providerDetails[31].substring(1, (providerDetails[31].length() - 1)).equals("MD")
                || providerDetails[31].substring(1, (providerDetails[31].length() - 1)).equals("DC")) {
        count++;

            // add provider to repository
        providers.add(convertToProvider(providerDetails));

        if (count % 1000 == 0) {
          providerRepository.save(providers);
          providers.clear();
          Thread.sleep(2000);
        }
      }
    }
此外,还必须刷新()EntityManager数据库并定期清除()

这很可能是内存不足的原因。

还必须刷新()EntityManager数据库并定期清除()


这很可能是内存不足的原因。

我怀疑最大的问题在于使用Hibernate将数据插入数据库的方式

当您调用
EntityManager.persist()
EntityManager.merge()
时,您正在使用的实体将被添加到
EntityManager
实例的PersistenceContext中(如前所述,了解实体生命周期是值得的)

您可以将PersistenceContext视为Hibernate使用的一种缓存,以避免对当前工作单元中已加载的对象进行不必要的数据库访问。此外,Hibernate使用PersistenceContext执行脏检查,以便在事务提交时了解需要刷新哪些对象

对于少量的对象,这是很好的。当您处理大量对象时,问题就出现了,因为Hibernate出于上述原因对PersistenceContext中的每个对象都保持引用

因此,在进行大批量插入时,您必须小心地管理PersistenceContext的大小,或者以一定的间隔显式地刷新和清除它,或者对批量插入使用无状态的
EntityManager


Hibernate很好地解释了如何一次性处理“很多”实体。我怀疑遵循这个建议可以解决大部分内存问题。

我怀疑最大的问题在于使用Hibernate将数据插入数据库的方式

当您调用
EntityManager.persist()
EntityManager.merge()
时,您正在使用的实体将被添加到
EntityManager
实例的PersistenceContext中(如前所述,了解实体生命周期是值得的)

您可以将PersistenceContext视为Hibernate使用的一种缓存,以避免对当前工作单元中已加载的对象进行不必要的数据库访问。此外,Hibernate使用PersistenceContext执行脏检查,以便在事务提交时了解需要刷新哪些对象

对于少量的对象,这是很好的。当您处理大量对象时,问题就出现了,因为Hibernate出于上述原因对PersistenceContext中的每个对象都保持引用

因此,在进行大批量插入时,您必须小心地管理PersistenceContext的大小,或者以一定的间隔显式地刷新和清除它,或者对批量插入使用无状态的
EntityManager


Hibernate很好地解释了如何一次性处理“很多”实体。我怀疑遵循这个建议可以解决大部分内存问题。

我将尝试回答你的具体问题,这是关于
Thread.sleep()
对内存问题的影响-我相信其他人会教你如何控制Hibernate的内存占用

我只知道一种情况,休眠应用程序线程有助于避免内存不足的情况,那就是大量使用定义了
Object.finalize()
方法的类的实例。此类实例经历了两轮可达性测试,必须执行finalize方法;作为垃圾收集的一部分,所有实例的finalize方法都在单个线程上执行。如果在多个线程上创建可终结垃圾的速度快于单个终结器线程的处理速度,则即使有大量垃圾可供收集,也会出现OutOfMemoryError。通过休眠来降低应用程序线程的速度,您可以给终结器线程一个迎头赶上的机会


在这种情况下,这几乎肯定不是您的问题(堆空间不足还有其他明显的原因),睡眠对您没有任何好处。

我将尝试回答您的具体问题,这是关于
线程的影响。sleep()
关于内存问题-我相信其他人会教你如何控制Hibernate的内存占用

我只知道一种情况,休眠应用程序线程有助于避免内存不足的情况,那就是大量使用定义了
Object.finalize()
方法的类的实例。此类实例经历了两轮可达性测试,必须执行finalize方法;作为垃圾收集的一部分,所有实例的finalize方法都在单个线程上执行。如果在多个线程上创建可终结垃圾的速度快于单个终结器线程的处理速度,则即使有大量垃圾可供收集,也会出现OutOfMemoryError。通过休眠来降低应用程序线程的速度,您可以给终结器线程一个迎头赶上的机会

在这种情况下,这几乎肯定不是您的问题(堆空间不足还有其他明显的原因),睡眠对您没有任何好处。

-Xms128m
-Xmx1536m
-XX:MaxPermSize=768m
-XX:-UseGCOverheadLimit