nan*_*no7 9 java multithreading equals arraylist hashcode
我有一个问题.当我尝试将"相同"对象两次添加到ArrayList时会发生什么."相同"是指单个类的对象,使用equals()和hashCode()标识为相同.它对于大多数成员变量具有不同的值,并且可能是从不同的线程创建的,但对于equals()和hashCode(),它们是"相同的".第二个对象是否会替换第一个对象?
另外,如果两个线程试图将这些对象完全同时添加到ArrayList会发生什么?这甚至可能吗?如果是,会发生什么?
谢谢!:-)
[编辑]感谢所有的答案!我应该使用synchronizedList,而不是使用"synchronize(list){}"吗? - >我读了docs,即使是使用synchronizedList,也可以使用迭代同步(list)
[EDIT2] synchronizedList可以声明为成员变量吗?我试过了,但它没有用.
Jon*_*eet 15
不,ArrayList
不会尝试完全检测重复 - 您可以ArrayList
使用完全相同的参考多次出现.如果你想有一个集合避免重复,你需要一个Set
实现-如果你也想保留插入顺序,你可能想LinkedHashSet
.
但请注意,如果没有锁定ArrayList
应该不是从多个线程在第一时间被突变-它只是并不意味着要以这种方式线程安全的集合.几个线程可以从没有同步的读取ArrayList
,但不能改变它.来自文档:
请注意,此实现不同步.如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步.(结构修改是添加或删除一个或多个元素的任何操作,或显式调整后备数组的大小;仅设置元素的值不是结构修改.)这通常通过同步一些自然封装的对象来实现.名单.如果不存在此类对象,则应使用Collections.synchronizedList方法"包装"该列表.这最好在创建时完成,以防止意外地不同步访问列表
如果你想在没有锁定的情况下从多个线程变异集合,我建议你看一下这些集合java.util.concurrent
.
第二个对象是否会替换第一个对象?
不,大多数开发人员都做了明确的检
if(!list.contains(foo)){
list.add(foo);
}
Run Code Online (Sandbox Code Playgroud)
另外,如果两个线程试图将这些对象完全同时添加到ArrayList会发生什么?这甚至可能吗?如果是,会发生什么?
是的,这是可能的.如果多个线程写入/读取相同的内容ArrayList
,则synchronized
每次访问此列表时都使用该关键字
public List<Foo> getFoos(){
synchronized(list){
return list;
}
}
public void addFoo(Foo foo){
synchronized(list){
list.add(foo);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
正如有人指出的那样,我想检查ArrayList
包含要添加的对象是否非常昂贵.如果你想确保只添加一次对象,我会遵循以下使用LinkedHashSet的建议.根据API,在尝试添加到此数据结构时
如果指定的元素尚不存在,则将其添加到此集合中.更正式地,如果此集合不包含元素e2(e == null?e2 == null:e.equals(e2)),则将指定元素e添加到此集合.如果此set已包含该元素,则调用将保持set不变并返回false.