java concurrent Array List访问

时间:2013-07-10 18:32:36

标签: java list collections concurrency

我有一个单身对象。该对象声明:

List<Player> players = new ArrayList<Player>();

同一个对象还在此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)

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)) {...
}

现在在构造函数中我这样做:

players = Collections.synchronizedList(new ArrayList<Player>());

但是同步这些方法的正确方法是什么。好像我在另一个类中使用iterator,它仍然会通过并发修改异常。如果2个线程同时调用“remove”和“contains”方法,是否会发生异常?有很多线程可以访问单例,所以我想知道以最小的性能命中来执行此操作的方法。

2 个答案:

答案 0 :(得分:11)

The documentation answers your question.

  

当迭代时,用户必须手动同步返回的列表:

List list = Collections.synchronizedList(new ArrayList());
      ...
  synchronized(list) {
      Iterator i = list.iterator(); // Must be in synchronized block
      while (i.hasNext())
          foo(i.next());
  }

至于containsremove,您不必手动同步。我正在查看Collections的源代码,看起来它适合你:

    public boolean contains(Object o) {
        synchronized (mutex) {return c.contains(o);}
    }
    public boolean remove(Object o) {
        synchronized (mutex) {return c.remove(o);}
    }

如果你必须自己做这些事情,它就不会是同步列表。

答案 1 :(得分:6)

如果您不打算更新它,请经常使用CopyOnWriteArrayList否则@ tieTYT的建议。

您也可以通过返回列表的副本而不是getPlayers中的实际列表来自行管理。 (如果您使用的是Collections.synchronizedList

public List<Player> getPlayers(){
    synchronized(list){
       Collections.unmodifiableList(new ArrayList<Player>(list));
    }
}

这有添加/删除后列表过期的副作用

修改 窃取Grzegorz对unmodifiableList的建议