Java 同时循环相同的列表安全吗?

Java 同时循环相同的列表安全吗?,java,multithreading,list,Java,Multithreading,List,我有一张单子 testList= new ArrayList<String>(); // gets initialized once at the very beginning init(). This list never changes. It's static and final. 我有很多线程同时使用这个方法并检查这个列表中是否有某个值。它似乎工作得很好。然而,我不确定这是否安全。我这样做对吗?它是线程安全的吗 只要在其他线程读取列表时没有线程修改列表,它就是线程安全的

我有一张单子

testList= new ArrayList<String>(); // gets initialized once at the very beginning init(). This list never changes. It's static and final. 

我有很多线程同时使用这个方法并检查这个列表中是否有某个值。它似乎工作得很好。然而,我不确定这是否安全。我这样做对吗?它是线程安全的吗

只要在其他线程读取列表时没有线程修改列表,它就是线程安全的

如果在列表上使用迭代器,则如果在迭代器下修改列表,它们将“快速失败”(如在throw
ConcurrentModificationException
)。其他访问方法(即
get(n)
)不会引发异常,但可能会返回意外结果


这在Javadoc for
List
ArrayList
中都有非常详细的介绍,您应该仔细研究。

只要没有线程在其他线程阅读列表时修改列表,它就是线程安全的

如果在列表上使用迭代器,则如果在迭代器下修改列表,它们将“快速失败”(如在throw
ConcurrentModificationException
)。其他访问方法(即
get(n)
)不会引发异常,但可能会返回意外结果


这在Javadoc for
列表和
ArrayList
中都有详细介绍,您应该仔细研究。

ArrayList
不是线程安全的对象。它现在可能适合您,但一般来说,在处理线程时,您应该确保使用的是线程安全对象,这些对象将按照您的预期处理线程

你可以用


testList=Collections.synchronizedList(新的ArrayList())

ArrayList
不是线程安全的对象。它现在可能适合您,但一般来说,在处理线程时,您应该确保使用的是线程安全对象,这些对象将按照您的预期处理线程

你可以用


testList=Collections.synchronizedList(新的ArrayList())

只要您能保证没有人在向列表中写入内容,它就安全了

请注意,即使列表是静态的和最终的,代码本身也不能保证列表不会被修改。我建议改用
Collections.unmodifiableList()
,因为它保证不会在列表中添加或删除任何元素


顺便说一下,您可以将代码重写为:

public static boolean isInList(String var1) {
    for (String s : testList) {
        if (Objects.equals(s, var1)) {
            return true;
        }
    } 
    return false;
}
或者只是

testList.contains(var1);

只要你能保证没有人在写名单,那就安全了

请注意,即使列表是静态的和最终的,代码本身也不能保证列表不会被修改。我建议改用
Collections.unmodifiableList()
,因为它保证不会在列表中添加或删除任何元素


顺便说一下,您可以将代码重写为:

public static boolean isInList(String var1) {
    for (String s : testList) {
        if (Objects.equals(s, var1)) {
            return true;
        }
    } 
    return false;
}
或者只是

testList.contains(var1);

是的,除非您正在添加/删除/更新列表中的元素。顺便说一下,使用另一个数据结构进行此类查询。例如,HashMap为什么不使用
testList.contains(var1)
?是的,除非您正在添加/删除/更新列表中的元素。顺便说一下,使用另一个数据结构进行此类查询。例如,hashMap为什么不使用
testList.contains(var1)
?而且,需要注意的是,列表必须首先安全地发布到每个线程。大多数处理线程引用的方法都很好;只是不要将其存储在非易失性静态字段中,让线程从中读取。同样值得注意的是,对于非线程安全列表(如ArrayList),您不能依赖ConcurrentModificationException的fail-fast行为,因为它所依赖的检查值很容易出现竞争条件。列表的迭代器方法(在for循环中调用)每次调用时都返回迭代器的新实例,因此,您可以在列表中同时循环多次而不会出现问题,而且,请注意,列表必须首先安全地发布到每个线程。大多数处理线程引用的方法都很好;只是不要将其存储在非易失性静态字段中,让线程从中读取。同样值得注意的是,对于非线程安全列表(如ArrayList),您不能依赖ConcurrentModificationException的fail-fast行为,因为它所依赖的检查值很容易出现竞争条件。列表的迭代器方法(在for循环中调用)每次调用时都返回迭代器的新实例,因此,您可以在列表中同时循环多次而不会出现问题