我已经设置了具有connection方法的send对象(我无法更改的库代码)。如果发送失败,他们将回调我实现的通用onClosed侦听器,该侦听器在我的代码中调用removeConnection(),这将从集合中删除连接。

onClosed回调是通用的,可以随时调用。例如,在对等方关闭连接时调用,而不仅仅是在写入失败时调用。

但是,如果我有一些循环遍历我的连接并发送的代码,则onClosed回调将尝试在迭代过程中修改集合。

我当前的代码在每次迭代之前创建连接列表的副本。但是,在剖析中这已显示非常昂贵。

Set<Connection> connections = new ....;

public void addConnection(Connection conn) {
    connections.add(conn);
    conn.addClosedListener(this);
}

@Override void onClosed(Connection conn) {
    connections.remove(conn);
}

void send(Message msg) {
    // how to make this so that the onClosed callback can be safely invoked, and efficient?
    for(Connection conn: connections)
        conn.send(msg);
}


在迭代过程中如何有效地修改集合?

最佳答案

ConcurrentSkipListSet可能是您想要的。

您也可以使用CopyOnWriteArraySet。当然,这仍然会产生副本,但是,只有在修改集后才会这样做。因此,只要不定期添加或删除Connection对象,这将更加有效。

10-04 14:07