假设我有一个名为Publisher
的类,其中有一个存储在WeakReference<>
列表中的Subscriber
对象列表。
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
可能已经被垃圾回收,因此在使用它之前需要检查是否为 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
检查?
for (final WeakReference<Subscriber> sub : subscribers) {
if (sub.get() != null) {
sub.get().update());
}
}
get()
后立即销毁对象,只要被get()
返回的强引用仍然在范围内。 - Alex Cohnget()
并检查结果是否为 null,但随后又再次调用了get()
,这并不能保证在那时它仍然是非 null 的。 - Jon Skeetif (sub.get() != null) { sub.get().update()); }
模式不好。 - Alex Cohn