java - 更新调度程序上的 Activity 集合

标签 java spring collections guava

我认为这可能是一件简单的事情,但想知道是否有这种模式或优雅的方式。我看了一眼 Guava 。 我有一个类级别列表,一个在调度程序上引用此 listOfObjects 的方法,以及一个在调度程序上更新它的方法。 updater 方法收集应在此列表中的所有对象,并准备好一个新列表来重新初始化 listOfObjects。但是,即使引用它的方法正在使用它,我是否应该设置它,或者是否有更安全的方法来执行此操作。

private List<Object> listOfObjects = new ArrayList<Object>();

@Scheduled
public referToList(){
    for(Object o : listOfObjects){
        doSomething(o);
    }
}

@Scheduled
public updateList(){
    List<Object> tempList = new ArrayList<Object>();
    tempList = doSomethingToPopulateList();
    this.listOfObjects = tempList;
}

因此,当referToList处于迭代过程中时,其可能的updateList可以是更新列表。我也可以在referToList中创建一个临时列表,因此它可以在listOfObjects的副本上工作,但不确定其效率如何

最佳答案

tl;dr - 您的代码是安全的,但可以使 future 的错误更具弹性。

首先,虽然不是立即必要的,但您应该倾向于选择不可变集合而不是可变集合,特别是在处理并发时。这样做是一个很好的做法,这样可以防止不必要的修改,并且可以更轻松地推断列表的状态。您的代码现在没有被破坏,如果其他线程在迭代时直接修改了 listOfObjects ,那么它就会被破坏,因此使其不可变可以防止这种情况发生。

换句话说,当分配给 listOfObjects 时,用 Collections.unmodifableList(tempList) 或 Guava 的 ImmutableList.copyOf(tempList) 包装列表(区别在于 Guava 的 ImmutableList 实际上创建了列表项的副本,而 unmodifableList 只是创建了一个不可变 View - 这意味着对基础列表的更改仍然会出现)。或者只是从 doSomethingToPopulateList() 返回一个不可变列表。

但是要回答您的问题,您正确的做法是不直接修改它,而是在将新列表收集到 tempList 中时更新 listOfObjects。即使 referToList() 当前正在执行,这也不会导致问题。这是因为 listOfObjects 是一个引用。当你运行时

for(Object o : listOfObjects){
    doSomething(o);
}     

JVM 在 for 循环开始时获取 listOfObjects 所引用的内存引用,并迭代该内存空间中的项目。当迭代发生时,您的其他代码可以更新 listOfObjects 所指向的内存引用(通过在 updateList() 中重新分配它),但这不会影响进度运行 for 循环的过程。

关于java - 更新调度程序上的 Activity 集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38385278/

相关文章:

java - 即使我有一个以 Object 作为参数的公共(public)构造函数,构造函数反射也不接受 Map 或 List 参数

java - java 8中的.net列表分组依据?

java - Collection <?扩展 T> 与集合 <T>

java - 如果我有一个列表和一个参数值,如何使用 updateBatch 删除行?

Spring Remoting HTTP 调用程序 - 异常处理

java - 使用迭代器和 iterator.remove() 时出现 ConcurrentModificationException

Java - 自定义形状面板?

spring - 使用 Wiremock 测试 Feign 客户端

Laravel 集合 group by with sum

java - 如何在为不包含重复项的项目指定特定逻辑的同时连接两个 Java 流?