java concurrent Array List访问

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)

至于containsremove,您不必手动同步.我正在查看源代码,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)

如果您必须自己完成这些工作,那么它不会是同步列表.

  • 请原谅我的无知,但那么'Collections.synchronizedList'的增值是什么?如果您在原始列表上同步,那么这不能解决所有问题吗? (2认同)

Joh*_*int 6

如果你不打算更新它,经常使用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