WeakHashMap 是在不断增长,还是清除了垃圾键? [英] Is WeakHashMap ever-growing, or does it clear out the garbage keys?

查看:31
本文介绍了WeakHashMap 是在不断增长,还是清除了垃圾键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 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?

推荐答案

是的,keys被清除垃圾真正被收集后

是的,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

添加4项后的尺寸:4

删除第 3 项后的大小:3

Size after removing item # 3: 3

item#2制作垃圾后的尺寸:2

Size after making garbage of item # 2: 2

就我而言,使用 Java 10.0.2 版本的 OpenJDK 基于 Azul Systems 的 ="nofollow noreferrer">Zulu JVM,垃圾收集器似乎正在激活应我的要求.如果我注释掉延迟一秒钟,或者 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

添加4项后的尺寸:4

删除第 3 项后的大小:3

Size after removing item # 3: 3

item#2制作垃圾后的尺寸:3

Size after making garbage of item # 2: 3

这篇关于WeakHashMap 是在不断增长,还是清除了垃圾键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆