【问题标题】:Is converting a defensive copy to a stream still thread-safe?将防御性副本转换为流仍然是线程安全的吗?
【发布时间】:2014-06-24 03:16:25
【问题描述】:

我有以下课程(省略批量代码):

public class SimpleEventBus implements EventBus {
    private final static Set<EventHandler> EMPTY_SET = Collections.emptySet();
    private final static EventHandler[] EMPTY_ARRAY = new EventHandler[0];
    private final static Supplier<Set<EventHandler>> CONCURRENT_SET_SUPPLIER =
            () -> Collections.newSetFromMap(new ConcurrentHashMap<>());

    private final ConcurrentMap<Class<?>, Set<EventHandler>> eventMapping = new ConcurrentHashMap<>();
    private final Class<?> eventClassConstraint;

    public SimpleEventBus() {
        this(Object.class);
    }

    public SimpleEventBus(final Class<?> eventClassConstraint) {
        this.eventClassConstraint = Objects.requireNonNull(eventClassConstraint);
    }

    ...

    @Override
    public void executeEvent(final Object event) {
        if (eventClassConstraint.isAssignableFrom(event.getClass())) {
            getCopyOfEventHandlers(event.getClass()).forEach(eventHandler -> eventHandler.invoke(event));
        }
    }

    ...

    private Stream<EventHandler> getCopyOfEventHandlers(final Class<?> eventClass) {
        Set<EventHandler> eventHandlers = eventMapping.get(Objects.requireNonNull(eventClass));
        return (eventHandlers == null) 
                ? Stream.empty()
                : Arrays.stream(eventHandlers.toArray(EMPTY_ARRAY));
    }

    ...

}

我想知道这里的getCopyOfEventHandlers 是否仍然返回该集合的线程安全副本。我知道我会这样写:

private EventHandler[] getCopyOfEventHandlers(final Class<?> eventClass) {
    Set<EventHandler> eventHandlers = eventMapping.get(Objects.requireNonNull(eventClass));
    return (eventHandlers == null) 
            ? EMPTY_ARRAY
            : eventHandlers.toArray(EMPTY_ARRAY);
}

但我想尽可能地从 Java 8 中受益,因此我决定这样做:

private Stream<EventHandler> getCopyOfEventHandlers(final Class<?> eventClass) {
    Set<EventHandler> eventHandlers = eventMapping.get(Objects.requireNonNull(eventClass));
    return (eventHandlers == null) 
            ? Stream.empty()
            : Arrays.stream(eventHandlers.toArray(EMPTY_ARRAY));
}

由于流使用延迟初始化,这仍然是线程安全的吗?这是否意味着生成的数组(来自 eventHandlers.toArray(EMPTY_ARRAY) 被隐式存储在内存中(被 GC 阻止)?

【问题讨论】:

    标签: java thread-safety java-8 java-stream


    【解决方案1】:

    eventHandlers.toArray(EMPTY_ARRAY) 确实会立即创建一个数组 - 只有流是惰性的。因此,从线程安全的角度来看,您的两个版本基本上是相同的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-06
      • 2019-04-09
      相关资源
      最近更新 更多