【问题标题】:How to correctly use VAVR collections to be thread safe?如何正确使用 VAVR 集合来保证线程安全?
【发布时间】:2018-02-21 14:20:50
【问题描述】:

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??
    }
}    

【问题讨论】:

    标签: java thread-safety vavr


    【解决方案1】:

    您可以将不可变 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));
        }
    
    }
    

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

    【讨论】:

    • 关闭应该被删除?
    【解决方案2】:

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

    @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());
        }
    
    }
    

    【讨论】:

    • 请记住,ConcurrentHashMap 只有同步的保存方法。读取方法不会被阻塞,因此您可以从映射中获取脏值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多