gpt4 book ai didi

java - 内存使用率不断增加资源和任务的数量保持不变我代码的问题意见

转载 作者:太空宇宙 更新时间:2023-11-04 09:11:44 25 4
gpt4 key购买 nike

在这个练习中,我有一些问题:“客户抱怨以下组件的内存使用量不断增加,尽管资源和任务的数量保持不变。解决此问题而无需更改Resource and Runner的公共API。”
给定练习的代码是`

import java.util.ArrayList;
import java.util.HashMap;

public class Runner {
private HashMap<Integer, Resource> resources = new HashMap<Integer, Resource>();

public Iterable<Resource> getResources() {
return this.resources.values();
}

public Resource acquireResource(int id) {
Resource w = this.resources.getOrDefault(id, null);
if (w == null) {
w = new Resource(id);
this.resources.put(id, w);
}

return w;
}

public void releaseResource(int id) {
Resource w = this.resources.getOrDefault(id, null);
if (w == null)
throw new IllegalArgumentException();

w.dispose();
}

public class Resource {
private ArrayList<String> tasks = new ArrayList<String>();

private int id;

public int getId() {
return this.id;
}

public Iterable<String> getTasks() {
return this.tasks;
}

public Resource(int id) {
this.id = id;
}

public void performTask(String task) {
if (this.tasks == null)
throw new IllegalStateException(this.getClass().getName());

this.tasks.add(task);
}

public void dispose() {
this.tasks = null;
}
}

public static void main(String[] args) {
Runner d = new Runner();

d.acquireResource(1).performTask("Task11");
d.acquireResource(2).performTask("Task21");
System.out.println(String.join(", ", d.acquireResource(2).getTasks()));
d.releaseResource(2);
Iterable it = d.getResources();
d.acquireResource(1).performTask("Task12");
System.out.println(String.join(", ", d.acquireResource(1).getTasks()));
d.releaseResource(1);
}
}


我认为此练习的解决方案应如下所示:

public void releaseResource(int id) {
Resource w = this.resources.getOrDefault(id, null);
if (w == null)
throw new IllegalArgumentException();
this.resources.remove(id);
w.dispose();
}


换句话说,我应该从资源hashTable中删除任务的ID。
这样正确吗?我应该在代码中添加或更改其他内容吗?

最佳答案

简短的答案:从资源映射中删除ID(就像您在代码段中所做的一样)是正确的方法。

长答案:问题代码的问题在于,仅调用w.dispose()只会从Resource对象中删除任务列表,这可能是最消耗内存的部分,但不是唯一的。

就像kaan在注释中解释的那样,该内存由java垃圾回收器释放,该垃圾回收器删除了堆内存中的每个对象,该对象不再被任何其他对象引用(因此无法访问和未使用)。因此,在调用w.dispose()之后,任务列表将从内存中删除。

现在的问题是HashMap<Integer, Resource>,因为java中的HashMap在内部只是一个大小增加的数组(由于将元素添加到该数组的方式,它有点复杂,但实际上,实际上只是一个数组以存储对象)。

HashMap的源代码:

/**
* The table, initialized on first use, and resized as
* necessary. When allocated, length is always a power of two.
* (We also tolerate length zero in some operations to allow
* bootstrapping mechanics that are currently not needed.)
*/
transient Node<K,V>[] table;


此数组包含添加到 Node的每个 HashMap。现在,由于 HashMap尝试默认情况下仅将Nodes放入阵列中字段的75%(使其空间效率降低,但速度更快),因此当添加许多 Node时,其大小必须增大。

HashMap的源代码中:

/**
* Implements Map.put and related methods
*
* @param hash hash for key
* @param key the key
* @param value the value to put
* @param onlyIfAbsent if true, don't change existing value
* @param evict if false, the table is in creation mode.
* @return previous value, or null if none
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
//...
if (++size > threshold)
resize();
//...
}

/**
* Initializes or doubles table size. If null, allocates in
* accord with initial capacity target held in field threshold.
* Otherwise, because we are using power-of-two expansion, the
* elements from each bin must either stay at same index, or move
* with a power of two offset in the new table.
*
* @return the table
*/
final Node<K,V>[] resize() {
//...
}


这意味着当您仅向 HashMap添加新条目(即使它们很小)时, HashMap的大小也会增加,因此尽管 table对象上调用了>方法。

但是,如果您从 dispose()中删除​​条目,则不需要调整大小(或至少不需要那么频繁),并且程序的已用内存不会一直在增长。

关于java - 内存使用率不断增加资源和任务的数量保持不变我代码的问题意见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59594964/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com