Java @singletonbean是否应该返回一个内部列表<&燃气轮机;成员?

Java @singletonbean是否应该返回一个内部列表<&燃气轮机;成员?,java,java-ee-6,Java,Java Ee 6,这可能是一个非常简单的问题,但我并不完全清楚 我有一个bean,如下所示: @Singleton @Startup @Lock(READ) public class SomeDataBean { List<Foo> foos; @PostConstruct public void init() { // Build foos; } public List<Foo> getFoos() { return foos; } @L

这可能是一个非常简单的问题,但我并不完全清楚

我有一个bean,如下所示:

@Singleton
@Startup
@Lock(READ)
public class SomeDataBean {
  List<Foo> foos;

  @PostConstruct
  public void init() {
    // Build foos;
  }

  public List<Foo> getFoos() {
    return foos;
  }

  @Lock(WRITE)
  public void modifyFoos() {
    // This could be potentially called too
  }
}
@Singleton
@启动
@锁(读)
公共类数据库{
列出食物;
@施工后
公共void init(){
//建立foos;
}
公共列表getFoos(){
返回foos;
}
@锁(写)
公共void modifyFoos(){
//这也可能被称为
}
}
随后,这个bean被注入(使用CDI-environment is Wildfly 8.2)到各种其他bean中(请求/会话/视图等),现在它们都可以访问这个
Foo
s列表。我的问题是,当另一个bean可能调用
modifyFoos()
时,按原样返回列表是否安全。或者这是一件永远不会发生的事情,并且是由容器保证的


我读过一些关于容器管理事务等的文档,但不完全清楚它在这种情况下是如何工作的。例如,用并发容器替换列表更好吗?

不,这是不安全的,因为一个线程可以读取列表,而另一个线程可以修改它

  • 返回列表的副本(如果有许多读取,则效率低下)
  • 使用列表
  • modifyFoos
    中存储列表的新实例

  • 如果您不希望列表数据被其他类更改,您可以返回一个副本,而不是原始列表的引用。@sgplait,大多数情况下我返回一个
    Stream()
    -我在示例中使用
    list
    ,因为它更通用一些。。。但同样的问题也适用于。。(好吧,流-除非由并发容器支持,否则不是线程安全的。!?!)要么返回列表的副本(防御副本),要么如果它是线程安全的,那么你就没有问题(迭代时也要小心,除非它是CopyOnWriteArrayList)。我希望得到一些容器魔法酱,啊,好吧,我会坚持退回副本。你能更具体地谈谈“容器魔法酱”吗?你也应该在那里使用一些同步。当你使用单例列表时,容器魔法帮不了你。如果与读相比,写是罕见的,那么您可以考虑选项3。对列表(或其他容器)的结构变化确实是罕见的。个人
    Foo
    s已正确同步-问题更多的是返回原始列表是否安全-对于我而言,对客户不切实际的期望。。。