contains方法的java.util.List是线程安全的吗?
我将java.util.List声明如下:contains方法的java.util.List是线程安全的吗?,java,multithreading,arraylist,Java,Multithreading,Arraylist,我将java.util.List声明如下: private static List<String> extensions = null; 私有静态列表扩展=null; 它总是由单个线程填充 但是多个线程可以同时调用扩展上的方法包含(E) 它是线程安全的吗?否,默认情况下,列表不是线程安全的。 如果你想让它线程安全。使用集合。synchronizedList()。否,默认情况下,列表不是线程安全的。 如果你想让它线程安全。使用集合.synchronizedList()。 列表在启动
private static List<String> extensions = null;
私有静态列表扩展=null;
它总是由单个线程填充
但是多个线程可以同时调用扩展上的方法包含(E)
它是线程安全的吗?否,默认情况下,列表不是线程安全的。
如果你想让它线程安全。使用集合。synchronizedList()。
否,默认情况下,列表不是线程安全的。
如果你想让它线程安全。使用集合.synchronizedList()。
列表在启动时由单个线程填充,以后无法修改。现在包含线程安全吗
如果您正在谈论一个ArrayList
,如标签所示,那么是的。谈论List
的线程安全是没有意义的,因为接口没有实现
查看arraylist的实现(),您可以看到它只读取共享状态,但不写入任何内容
但要小心:
List
。您能否保证存储在该字段中的变量的运行时类型始终为ArrayList
如果一个线程正在插入数据,而另一个线程正在调用
Contains
,那么这将不是线程安全的。考虑<代码>添加< /代码>的实现:
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacity(size+1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
假设您有一个包含4个元素的列表,其内部数组的容量为6。内部数组看起来像这样{a,b,c,d,null,null}
,私有字段大小将设置为4,以限定列表的边界
如果我现在在位置2插入x
,将会发生以下情况:
arraycopy
将c
和d
向右移动,就像{a,b,c,c,d,null}
下一行将插入x
,{a,b,x,c,d,null}
下一行将size
增加到5,更新列表的边界
注意,如果在步骤1和步骤3之间调用列表中的Contains(d)
,将返回false
。这是因为size
仍然设置为4,并且列表似乎包含{a,b,c,c}
,而{d,null}
将被忽略
列表在启动时由单个线程填充,以后无法修改。现在包含线程安全吗
如果您正在谈论一个ArrayList
,如标签所示,那么是的。谈论List
的线程安全是没有意义的,因为接口没有实现
查看arraylist的实现(),您可以看到它只读取共享状态,但不写入任何内容
但要小心:
您的字段类型为List
。您能否保证存储在该字段中的变量的运行时类型始终为ArrayList
更重要的问题是:文档是否说该方法是线程安全的?否则,Java的未来版本可能会使它变得不安全,这不会被认为是一个破坏性的改变
如果一个线程正在插入数据,而另一个线程正在调用Contains
,那么这将不是线程安全的。考虑<代码>添加< /代码>的实现:
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacity(size+1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
假设您有一个包含4个元素的列表,其内部数组的容量为6。内部数组看起来像这样{a,b,c,d,null,null}
,私有字段大小将设置为4,以限定列表的边界
如果我现在在位置2插入x
,将会发生以下情况:
arraycopy
将c
和d
向右移动,就像{a,b,c,c,d,null}
下一行将插入x
,{a,b,x,c,d,null}
下一行将size
增加到5,更新列表的边界
注意,如果在步骤1和步骤3之间调用列表中的Contains(d)
,将返回false
。这是因为size
仍然设置为4,并且列表似乎包含{a,b,c,c}
,而{d,null}
将被忽略
列表在启动时由单个线程填充,以后无法修改。现在包含线程安全吗
以这种方式使用的对象称为“有效不可变”——程序可以更改对象,但不能更改。Brian Goetz的书《Java并发实践》中有一节专门讨论有效不可变对象的安全发布
简单的回答(假设我记得正确)是,如果在构造函数中填充列表,并且在构造函数返回之前没有其他线程可以访问该列表,那么该列表将安全发布。当然,我假设你放在列表中的项目实际上也是不变的
“安全发布”意味着其他线程将保证在其预期的最终状态下查看列表。如果列表未安全发布,则在不同处理器上运行的线程可能会看到不同版本的列表(可能包括列表处于不一致状态的某些版本,当您尝试访问它时,可能会使程序崩溃)
列表在启动时由单个线程填充,以后无法修改。现在包含线程安全吗
以这种方式使用的对象称为“有效不可变”——程序可以更改对象,但不能更改。Brian Goetz的书《Java并发实践》中有一节专门讨论安全pu