具有弱引用和标识哈希的并发集

r.v*_*r.v 5 java concurrency weak-references set guava

我想要一个对元素的弱引用的并发集.我想过用Guava做这件事MapMaker:

Set<Object> concurrentSet = Collections.newSetFromMap(
    new MapMaker<Object, Boolean>().weakKeys().makeMap());
Run Code Online (Sandbox Code Playgroud)

Guava将自动为您提供弱键的身份哈希.然而,事实证明,MapMaker不允许类型参数.

file.java:123 type com.google.common.collect.MapMaker does not take parameters
                new MapMaker<Object, Boolean>().weakKeys().makeMap());
                            ^
Run Code Online (Sandbox Code Playgroud)

任何解决方案如何获得具有弱元素引用的并发集?

Bas*_*que 6

为了充实在接受的答案和评论中暗示的代码,这是我自己对代码的看法,以获得并发弱集.

Java,没有番石榴

使用类文档中建议的习语,使用Collections.newSetFromMap将并发Map包装为Set.使用Boolean地图的值类型只是填充,无关紧要.

Set< YourObjectTypeGoesHere > concurrentWeakSet = 
    Collections.synchronizedSet(
        Collections.newSetFromMap(
            new WeakHashMap< YourObjectTypeGoesHere , Boolean >()
        )
    )
;
Run Code Online (Sandbox Code Playgroud)

可以推断出参数化类型,将代码简化为:

Set< YourObjectTypeGoesHere > concurrentWeakSet = 
    Collections.synchronizedSet(
        Collections.newSetFromMap(
            new WeakHashMap<>()     // Types inferred, so omitted.
        )
    )
;
Run Code Online (Sandbox Code Playgroud)

番石榴

或者,我们可以使用MapMakerGoogle Guava库.

我们不是使用包装WeakHashMap的 doc的示例,而是根据Guava doc的建议将WeakHashMap替换为来自Google GuavaMapMaker的地图new MapMaker().weakKeys().makeMap().Guava doc指出,这个地图"使用对象标识比较密钥,而WeakHashMap使用Object.equals".

用法

使用它比理解它更容易!

实例化

要创建并发弱集,请复制粘贴以下代码.替换两次出现YourObjectTypeGoesHere.

int level = 16; // Basically, the approximate number of threads that may simultaneously try to mutate the map. See Guava doc.
ConcurrentMap<YourObjectTypeGoesHere , Boolean> concurrentWeakMap = new MapMaker().concurrencyLevel( level ).weakKeys().makeMap(); // Google Guava team recommends MapMaker > weakKeys > makeMap as a replacement for weakHashMap.
Set<YourObjectTypeGoesHere> concurrentWeakSet = Collections.newSetFromMap( concurrentWeakMap ); // Concurrency protection carries over to Set wrapper.
Run Code Online (Sandbox Code Playgroud)

加上

要添加到集:

concurrentWeakSet.add( myObject ); 
Run Code Online (Sandbox Code Playgroud)

迭代

要访问集合中的元素:

Iterator<YourObjectTypeGoesHere> iterator = concurrentWeakSet.iterator();
while(iterator.hasNext()) {
    YourObjectTypeGoesHere myObject = iterator.next();
    if( myObject != null ) { // Not sure if needed. Is it possible for object to be garbage-collected but not yet have its entry removed from the Set/Map?
       // Work with the object.
    }
}
Run Code Online (Sandbox Code Playgroud)

去除

弱势意味着不需要删除元素.随着元素被废弃和垃圾收集,它们从我们的集合(Map/Set)中消失.


m0s*_*it0 5

文档中所述,MapMaker不是通用类型; 它是<Object, Object>.这意味着您可以将任何内容作为键或值放置,只需在撤消时进行转换即可.引用链接:

   ConcurrentMap<Request, Stopwatch> timers = new MapMaker()
       .concurrencyLevel(4)
       .weakKeys()
       .makeMap();
Run Code Online (Sandbox Code Playgroud)

为了得到一个SetMap条目,你只需要调用Map#entrySet().

  • 您仍然需要原始问题中所示的`Collections.newSetFromMap`. (4认同)