安全地使用WeakReference

时间:2016-02-24 15:43:18

标签: java garbage-collection weak-references

假设我有一个班级Publisher,其中Subscriber列表中存储了WeakReference<>个对象

public interface Subscriber {
    void update();
}

public class Publisher {
    private final List<WeakReference<Subscriber>> subscribers = new CopyOnWriteArrayList<>();

    public void subscribe(final Subscriber subscriber) { 
        subscribers.add(new WeakReference<>(subscriber)); 
    }

    public void publish() { ...

在调用Publisher::subscribe和稍后调用Publisher::publish之间,弱引用列表中的Subscriber可能已被垃圾回收,因此我需要检查它是否为{{ 1}}使用之前。

我的问题是,对于null,下面的代码是否安全可靠?

publish

是否有可能在过滤public void publish() { //filter out garbage collected items subscribers = subscribers.stream() .filter(sub -> sub.get() != null) .collect(Collectors.toList()); //use the remaing objects for (final WeakReference<Subscriber> sub : subscribers) { sub.get().update()); } } 和调用subscribers之间垃圾收集器已经破坏了另一个对象? 我应该在更新时进行第二次Subscriber::update检查吗?

null

1 个答案:

答案 0 :(得分:5)

您建议的第二次无效检查也不够好,因为第一次调用get()可能会返回非空值,第二次调用可能会返回null。我建议:

for (WeakReference<Subscriber> subRef : subscribers) {
    Subscriber sub = subRef.get();
    if (sub != null) {
        sub.update();
    }
}

或者使用Java 8的流(未经测试):

subscribers
    .stream()
    .map(WeakReference::get)
    .filter(s -> s != null)
    .forEach(Subscriber::update);