Art*_*lev 4 java collections concurrency list
我有一个单身的物体.该对象声明:
List<Player> players = new ArrayList<Player>();
Run Code Online (Sandbox Code Playgroud)
同一个对象还在此arrayList上指定了4个操作:
public List<Player> getPlayers() {
return players;
} // the result of this method can be used in another object as an iterator (or maybe by index-access)
Run Code Online (Sandbox Code Playgroud)
和
public void removePlayer(Player player) {
players.remove(player);
}
public void addPlayer(Player player) {
players.add(player);
}
public boolean isPresent(Player player) {
if (players.constans(player)) {...
}
Run Code Online (Sandbox Code Playgroud)
现在在构造函数中我这样做:
players = Collections.synchronizedList(new ArrayList<Player>());
Run Code Online (Sandbox Code Playgroud)
但是同步这些方法的正确方法是什么.好像我在另一个类中使用iterator,它仍然会通过并发修改异常.如果2个线程同时调用"remove"和"contains"方法,是否会发生异常?有许多线程可以访问单例,所以我想知道以最小的性能命中执行此操作的方法.
Dan*_*lan 11
当迭代它时,用户必须手动同步返回的列表:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
Run Code Online (Sandbox Code Playgroud)
至于contains和remove,您不必手动同步.我正在查看源代码,Collections它看起来像是为你做的:
public boolean contains(Object o) {
synchronized (mutex) {return c.contains(o);}
}
public boolean remove(Object o) {
synchronized (mutex) {return c.remove(o);}
}
Run Code Online (Sandbox Code Playgroud)
如果您必须自己完成这些工作,那么它不会是同步列表.
如果你不打算更新它,经常使用CopyOnWriteArrayList,否则@ tieTYT的建议有效.
您也可以通过返回列表的副本而不是实际的列表来自行管理getPlayers.(如果你正在使用Collections.synchronizedList)
public List<Player> getPlayers(){
synchronized(list){
Collections.unmodifiableList(new ArrayList<Player>(list));
}
}
Run Code Online (Sandbox Code Playgroud)
这有添加/删除完成后列表过期的副作用
编辑: 窃取Grzegorz的建议unmodifiableList