【发布时间】:2016-03-18 04:26:34
【问题描述】:
我的应用程序在执行包含大量数据的操作时内存不足。数据是一个 Java 列表,大小约为 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 后不需要它。
我上面的分析错了吗?我只需要增加最大堆,因为我正在处理大数据?
【问题讨论】:
-
很难从您提供的内容中分辨出来,当前实现的一个明显问题是重复调用persistData 将启动的线程数没有限制。足够频繁地调用它,您很容易耗尽资源。您可能需要考虑使用队列和消费者或线程池方法。
-
您能否展示您如何设置列表/列表中的内容。
-
您确定需要为每个列表创建 PersistDataIntoDB dbPersist 吗?看起来这是一个带有静态方法的类。
-
@Jan 列表包含我的数据结构之一的元素。数据结构 ClassA 与 ClassB 略有不同,因此,我为 ClassA 的每个对象构造 ClassB 的对象,这是调用者提供的列表。
-
你能展示一下constructClassBUsingClassA的完整代码吗?不清楚如何将一个类转换为另一类?
标签: java performance memory-management