我有一个生成记录的数据生成代码,每个记录都有多个用户选择的字段。为了加快进程,我正在分割任务以批量创建记录,以并行创建记录
例如:如果我想生成10k记录,我将它分成5个任务
喜欢说
Task 1 : create record from 1-2k
Task 2 : create record from 2001-3k
...
Task 5 : create record from 8001-10k
我希望每个线程都将记录存储在容器中。当容器填充到一个限制,例如初始1k记录,然后一个等待导出数据的任务将开始按顺序删除记录。
我的选择是使用Hash Map,因为序列很重要,但它的内存效率并不高,因为即使Map是空的超过50%,Map上的Map占用的大小保持不变,直到Map为GC。
因此,考虑到我的上述情况,最适合容器的是什么?
答案 0 :(得分:0)
在谈论大尺寸时,将记录存储在内存中并不是一个好习惯。在批量检索数据时将数据推送到持久性dB存储。 如果保留数据的索引ID,则可以从那里处理连续的存储顺序。
如果您热衷于使用Hashmap: 您可以在初始化对象时指定负载率。这限制了底层哈希表中未使用的空间量。当然,限制这个未使用的空间会导致性能下降,因为在哈希表中会有更多的冲突。 你还需要调整你的GC,看看这个 -
http://www.cubrid.org/blog/dev-platform/how-to-tune-java-garbage-collection/][1]
但我仍然建议按照之前的建议修改你的设计
答案 1 :(得分:0)
您可能不需要关心垃圾收集器。所有内存仅在调用垃圾收集器时释放 - 它将永远不会被释放。如果您的程序功能正确并且不保留对未使用数据的任何引用,则垃圾收集器将清除所有未使用的对象。
在此处查看此问题:
confusion-over-how-javas-garbage-collector-works-nodes-queue
您可以使用数组来存储对象的引用。如果使用新引用覆盖引用,则垃圾收集器将收集数组中的旧对象。否则,您将不得不抛弃数组或手动将任何未使用的引用设置为null,以允许GC重用引用。
您可以使用ArrayList
,在这种情况下,您可以调用clear()
清空它并释放引用。或者你可以扔掉ArrayList
并重新分配它。
另请参阅此处:java-collections-and-garbage-collector
如果你真的想避免分配和重新分配内存,你将不得不担心重复使用持有个人记录的对象,这可能会非常困难,而且可能无效。
答案 2 :(得分:0)
ArrayList是个不错的选择。 ArrayList具有remove方法,该方法应该用于删除对象。 ArrayList clear()方法也会有所帮助。但是,正如您所指出的,您将不得不等待GC。
最有效的内存方式是使用原始数据类型,如字符数组和整数数组。这是因为Java中的原始数据类型是唯一没有被垃圾收集的数据类型。
are java primitives garbage collected
除了primitive之外的其他所有东西都是Java中的Object。并且所有对象在实例化时都有内存分配,没有选项可以释放但是有资格进行垃圾收集。
答案 3 :(得分:-1)