是WeakHashMap不断增长,还是清除垃圾密钥? [英] Is WeakHashMap ever-growing, or does it clear out the garbage keys?
问题描述
我正在尝试使用 WeakHashMap
作为并发 Set
弱引用.
I am trying to use WeakHashMap
as a concurrent Set
of weak references.
this.subscribers =
Collections.synchronizedSet(
Collections.newSetFromMap(
new WeakHashMap <>()
)
);
当一个元素进入垃圾收集时,我的集合继续将其报告为收集的一部分.因此,地图似乎正在不断增长.
When an element goes to garbage-collection, my set continues to report it as a part of the collection. So it seems the map is ever-growing.
文档说:
钥匙遗失后,其条目会从地图上有效删除,……
When a key has been discarded its entry is effectively removed from the map,…
但是实际上似乎并非如此.
But that does not seem to be the case in practice.
WeakHashMap
是否有清除碎屑的地方?
Is there ever a point at which the WeakHashMap
clears out the detritus?
推荐答案
是的,实际上是在垃圾被收集后在清除的键
是的,WeakHashMap
确实清除了碎屑.用于垃圾回收的密钥不再按大小报告.但是您必须等待垃圾收集真正发生.
Yes, keys cleared after garbage is actually collected
Yes, WeakHashMap
does clean out the detritus. The keys that have gone to garbage collection are no longer reported in the size. But you must wait for garbage-collection to actually take place.
对于您的对象进行垃圾回收,您似乎不正确.也许您的对象成为了候选对象以进行垃圾收集,但尚未被收集.尝试调用垃圾收集器,然后等待它完成.但是请记住,对System.gc()
的调用仅是对JVM的建议,根据您的JVM实现和当前的运行时情况,可能会被忽略.
Seems likely that you were incorrect about your objects going to garbage-collection. Perhaps your objects became candidates for garbage-collection, but have not yet been collected. Try invoking the garbage-collector and waiting a moment for it to complete. But remember, the call to System.gc()
is only a suggestion to the JVM and may be ignored depending on your JVM implementation and current runtime scenario.
这是一个完整的示例应用程序.请注意,无论是调用Set::remove
还是让对象超出范围,Set
都会报告size
的减小.
Here is a complete example app. Notice that the Set
reports a decrease in size
whether calling Set::remove
or letting the object go out of scope.
package com.basilbourque.example;
import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
public class WeakHashMapExercise {
public static void main ( String[] args ) {
WeakHashMapExercise app = new WeakHashMapExercise();
app.doIt();
}
private void doIt ( ) {
Set < UUID > set =
Collections.synchronizedSet(
Collections.newSetFromMap(
new WeakHashMap <>()
)
);
UUID uuid1 = UUID.fromString( "a8ee1e34-cead-11e8-a8d5-f2801f1b9fd1" );
UUID uuid2 = UUID.fromString( "39bda2b4-5885-4f56-a900-411a49beebac" );
UUID uuid3 = UUID.fromString( "0b630385-0452-4b96-9238-20cdce37cf55" );
UUID uuid4 = UUID.fromString( "98d2bacf-3f7f-4ea0-9c17-c91f6702322c" );
System.out.println( "Size before adding: " + set.size() );
set.add( uuid1 );
set.add( uuid2 );
set.add( uuid3 );
set.add( uuid4 );
System.out.println( "Size after adding 4 items: " + set.size() ); // Expect 4.
set.remove( uuid3 );
System.out.println( "Size after removing item # 3: " + set.size() ); // Expect 3.
uuid2 = null; // Release that UUID to garbage-collection.
// That released object may still appear in our `Set` until garbage collection actually executes.
System.gc(); // Ask the JVM to run the garbage-collection. Only a suggestion, may be ignored.
try {
Thread.sleep( 1_000 ); // Wait a moment, just for the heck of it.
} catch ( InterruptedException e ) {
e.printStackTrace();
}
System.out.println( "Size after making garbage of item # 2: " + set.size() ); // Expect 2.
for ( UUID uuid : set ) {
System.out.println( uuid.toString() );
}
}
}
请参见此在IdeOne.com上实时运行的代码.
添加前的大小:0
Size before adding: 0
添加4个项目后的大小:4
Size after adding 4 items: 4
删除项目3:3后的尺寸
Size after removing item # 3: 3
丢弃项目2:2后的尺寸
Size after making garbage of item # 2: 2
就我而言,使用System.gc
呼叫,那么报告的最后一个大小仍然是3
而不是预期的2
.
In my case, using Java 10.0.2 version of OpenJDK-based Zulu JVM from Azul Systems, the garbage collector does seem to be activating upon my request. If I comment out the delay for a second, or the System.gc
call, then the last size reported remains 3
rather than the expected 2
.
当在IdeOne.com上实时运行此代码时,您甚至可以看到此行为.请注意,下面的最后一个项目是3
,但是上面的是2
.
You can even see this behavior when running this code live at IdeOne.com. Notice how the last item below is 3
but above is 2
.
添加前的大小:0
Size before adding: 0
添加4个项目后的大小:4
Size after adding 4 items: 4
删除项目3:3后的尺寸
Size after removing item # 3: 3
丢弃项目2:3后的尺寸
Size after making garbage of item # 2: 3
这篇关于是WeakHashMap不断增长,还是清除垃圾密钥?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!