4

VAVR 集合是“不可变的”。

那么,如果我有静态变量,例如,保存所有 WebSocket 会话,我将如何使用 VAVR 以便集合是线程安全的?

例如:

@ServerEndpoint("/actions")
public class DeviceWebSocketServer {

    private static Set<Session> sessions = //???; // how should I initialize this?

    @OnOpen
    public void open(Session session) {
        sessions = sessions.add(session); // is this OK???
    }

    @OnClose
    public void close(Session session) {
        sessions = sessions.remove(session); // is this OK??
    }
}    
4

2 回答 2

11

您可以将不可变 vavr 集合包装在原子可更新的AtomicReference中,并使用其更新方法之一以原子方式更新对不可变集合的引用。

@ServerEndpoint("/actions")
public class DeviceWebSocketServer {

    private static AtomicReference<Set<Session>> sessionsRef = 
            new AtomicReference<>(HashSet.empty());

    @OnOpen
    public void open(Session session) {
        sessionsRef.updateAndGet(sessions -> sessions.add(session));
    }

    @OnClose
    public void close(Session session) {
        sessionsRef.updateAndGet(sessions -> sessions.remove(session));
    }

}

如果您打算在其他场景中使用它们,请确保您阅读了 javadoc AtomicReference,因为更新功能需要遵守一些要求才能获得正确的行为。

于 2018-02-21T15:06:53.163 回答
-1

对于这个用例,您还可以考虑使用并发映射:

@ServerEndpoint("/actions")
public class DeviceWebSocketServer {

    private static ConcurrentMap<String, Session> sessions = new ConcurrentHashMap<>();

    @OnOpen
    public void open(Session session) {
        sessions = sessions.putIfAbsent(session.getId(), session);
    }

    @OnClose
    public void close(Session session) {
        sessions = sessions.remove(session.getId());
    }

}
于 2018-02-22T10:17:31.193 回答