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

查看:167
本文介绍了是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?

推荐答案

是的,实际上是在垃圾被收集后在清除的键

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

就我而言,使用 Java 10.0.2 版本"rel =" nofollow noreferrer>基于OpenJDK 的来自 Azul Systems 的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

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屋!

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