本文介绍了垃圾收集在内部地图中跟踪自己的实例的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的类的构造函数中,我将当前对象( this )映射到一个静态LinkedHashMap中,并将其键(一个作为构造函数中的参数输入的字符串)映射到一个静态的LinkedHashMap中,所以我可以引用对象由字符串在任何地方我可能会需要它。

In the constructor of my class, I map the current object (this), along with its key (a string entered as a parameter in the constructor) into a static LinkedHashMap so I can reference the object by the string anywhere I might need it later.

这是代码(如果有帮助):

Here's the code (if it helps):

public class DataEntry {
    /** Internal global list of DataEntry objects. */
    private static LinkedHashMap _INTERNAL_LIST;

    /** The data entry's name. */
    private String NAME;

    /** The value this data entry represents. */
    private Object VALUE;


    /** Defines a DataEntry object with a name and a value. */
    public DataEntry( String name, Object value )
    {
        if( _INTERNAL_LIST == null )
        {
            _INTERNAL_LIST = new LinkedHashMap();
        }

        _INTERNAL_LIST.put( name, this );

        NAME = name;
        VALUE = value;
    }
}

问题?这个类的实例在使用它们时不会收到垃圾。

The problem? Instances of this class won't get garbage collected when I'm done using them.

我只是好奇,如果有办法让这个类的实例清理自己当我完成使用它们,而不必手动调用一个Remove()方法或每次(删除其内部LinkedHashMap中的引用,当我不再使用它们,我的意思)。

I'm just curious if there's a way to have instances of this class clean themselves up when I'm done using them without having to manually call a Remove() method or something each time (to remove its reference in the internal LinkedHashMap when I'm no longer using them, I mean).

推荐答案

在其构造函数完成之前让对象可见,不是线程安全的。

Making an object visible to others before its constructor is complete is not thread safe.

在这种情况下,如何使用地图是不清楚的,但假设在类中有一个这样的静态方法:

It's not clear how the map is being used in this case, but suppose there's a static method like this in the class:

public static DataEntry getEntry(String name) {
  return _INTERNAL_LIST.get(name);
}

同时运行的另一个线程可以访问 DataEntry 在创建时,开始使用未初始化的 VALUE 的条目。即使您重新排序构造函数中的代码,以便将新实例添加到地图是最后一件事情,JVM允许重新排序指令,以便将对象添加到列表中。或者,如果类被扩展,子类初始化可能会在对象发布之后发生。

Another thread, running concurrently, can access a DataEntry while it is being created, and start to use an entry with an uninitialized VALUE. Even you reorder the code in the constructor so that adding the new instance to the map is the last thing you do, the JVM is allowed to reorder the instructions so that the object is added to the list first. Or, if the class is extended, the subclass initialization could take place after the object has been published.

如果多个线程访问与$ $ c $的交互c> DataEntry 类,你可能会有一个平行依赖的,间歇性的,非常难以诊断的并发错误。

If more than one thread accesses the interacts with the DataEntry class, you could have a concurrency bug that is platform dependent, intermittent, and very tough to diagnose.

brian Goetz的href =http://www.ibm.com/developerworks/java/library/j-jtp0618.html#2 =nofollow noreferrer>安全建设有更多的信息关于这个主题。

The article, "Safe Construction," by Brian Goetz has more information on this topic.

回到原来的问题:使用 WeakReference ,如其他人所提到的,是一个很好的方法,而不是迭代地图中的每个条目,我建议为您的值创建一个包装器,扩展 WeakReference (可能是您的 DataEntry 本身或一个帮助者),并在。这样,您可以快速轮询任何收集的条目的队列,并从地图中删除它们。这可以通过后台线程完成(阻止在)在类初始化程序中启动,或者可以清除任何陈旧的条目(由)。

Back to the original question: using WeakReference, as mentioned by others, is a good approach, but rather than iterating over every entry in the map, I'd recommend creating a wrapper for your values that extends WeakReference (it could be your DataEntry itself, or a helper), and queuing each reference in a ReferenceQueue. That way, you can quickly poll the queue for any collected entries, and remove them from the map. This could be done by a background thread (blocking on remove) started in a class initializer, or any stale entries could be cleaned (by polling) each time a new entry is added.

如果您的程序是多线程的,您应该放弃,或者将 LinkedHashMap 与。

If your program is multi-threaded, you should abandon LinkedHashMap for a map from java.util.concurrent, or wrap the LinkedHashMap with Collections.synchronizedMap().

这篇关于垃圾收集在内部地图中跟踪自己的实例的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 23:37