我的应用程序在执行大数据操作时内存不足。数据是Java List,大小约为100K元素。
PersistData
是实现操作的类,PersistDataIntoDB
是执行实际操作的类。由于操作耗时,PersistData
的调用者会得到一个响应,说明操作已经开始,并且还有其他API来获取操作的状态。
此外,整个操作并发,并且有多个调用者进行操作。
这是代码的样子(我希望它的可读性)。
public class PersistData {
public Boolean persistData(List<ClassA> dataRecs) {
//some checks (smaller operation)
persistDataInDifferentThread(dataRecs);
//if no errors in checks return true
return true;
}
private void persistDataInDifferentThread(List<ClassA> dataRecs) {
Thread runnerThread = new Thread(new Runnable() {
public void run() {
try {
List convertedList = constructClassBUsingClassA(dataRecs);
PersistDataIntoDB dbPersist = new PersistDataIntoDB();
dbPersist.persistDataInDB(convertedList);
}
catch (Exception e) {
}
}
});
}
private List<ClassB> constructClassBUsingClassA(List<ClassA> dataRecs) {
List<ClassB> tempList = new ArrayList<ClassB>();
for (int i = 0; i < dataRecs.size(); i++) {
ClassA tempRec = dataRecs.get(i);
ClassB tempRecB = new ClassB();
//put stuff from tempRec to tempRecB
tempList.add(tempRecB);
}
return tempList;
}
}
执行持久性的类。
public class PersistDataIntoDB {
public Boolean persistDataInDB(List<ClassB> dataRecs){
//if all goes well return true
return true;
}
}
我的问题是我的方法persistDataInDifferentThread
是否可以重构?因为在它运行时,内存中有两个大的列表,对persistDataInDB
的调用需要很长时间才能完成,垃圾收集器可能会即使我在调用List<ClassA>
之后不需要它,也不会卸载persistDataInDB
。
我的上述分析是错误的吗?我只需要增加最大堆,因为我正在处理大数据?
答案 0 :(得分:2)
我的上述分析是错误的吗?我只需要增加最大堆,因为我正在处理大数据?
是的,是的。
1)使用多个线程不会增加或减少使用的堆空间量。
2)如果堆填满,那么JVM会在投掷OOME之前尽力回收空间。
唯一可能产生影响的是,如果一个线程创建了列表并将其传递给第二个实例以进行持久化......并且还挂起到列表的引用。这可能导致列表保持可访问的时间超过其需要的时间。
如果你有多个跑步者线程持久存在多个列表,我猜你也会遇到麻烦,而且工作的到达时间比你处理它的速度快。如果这是问题所在,那么您需要做一些事情来控制接受请求的速率。