【问题标题】:Is using System.identityHashCode(Obj) reliable to return unique Id使用 System.identityHashCode(Obj) 可靠返回唯一 ID
【发布时间】:2015-01-10 16:04:47
【问题描述】:

我在 dropwizard 服务中实现了 websocket,他们需要在服务器端实现会话管理。在连接时,我们得到会话对象,它是客户端和服务器之间的通信链接。但他们不是获取像 session.getId() 这样的会话唯一 ID 的方法,我需要 id 进行会话管理。

所以我一直在考虑使用 System.identityHashCode(Session) 来获取唯一 ID 并使用此 ID 处理会话。

websocket onConnect 结构仅供参考

@OnWebSocketConnect
public void onOpen(Session session) throws IOException
{    
 // code to add the session in session management using unique id
}

那么使用 System.identityHashCode(Session) 会好吗?

【问题讨论】:

  • 你的会话是什么?没有某种唯一标识符,会话就无法存在——它就是将会话定义为会话的原因。
  • @Dunes Session 表示与远程 WebSocket 端点download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/…的通信的活动链接
  • 您能否在不访问会话的情况下重新创建密钥?如果没有,您不妨使用集合而不是地图来存储会话。

标签: java session websocket uniqueidentifier


【解决方案1】:

identityHashMap 通常从内存地址或与线程绑定的随机数生成器派生,然后在 JVM 首次使用时存储在对象头中。碰撞的可能性很低,但并非不可能。

鉴于可能发生碰撞,为什么要冒险呢?这可能导致的错误将是微妙且令人恼火的追踪。

【讨论】:

  • 所以在 GC 收集之前,他们无法在对象的整个生命周期中获得唯一性
  • @Ninad JVM 确实知道背后的唯一性,请参阅 IdentityHashMap 和相等运算符。但是,使用对象生成和存储 GUID 可能会更简单。
  • 顺便说一句,我相信在 Oracle JVM 上,用于标识哈希码的标头字节与用于偏向锁定的字节相同。这意味着它们不能同时使用,因此如果要在对象上调用标识哈希码,然后在同步语句中使用它,那么 JVM 将永远无法将锁偏向该线程。
  • 值得注意的是,Session 对象本身可能不会在方法调用之外持续存在。也就是说,对于每个方法调用,可能会创建一个新的 Session 对象,并使用与旧 Session 对象相同的数据进行初始化。这意味着您可能会遇到多个 Sessions 对象引用同一个会话,但内存地址不同的情况。
【解决方案2】:

WebSocketSessionSession 的实现。它覆盖了hashCodeequals,因此可以在使用超过 4GB 内存的程序中安全地进行散列。也就是说,会话关键。

你可以这样做:

class YourClass 
{

    private Set<Session> managedSessions = new HashSet<Session>();
    // or use a Map<Session,Data> if you want to store associated data

    @OnWebSocketConnect
    public void onOpen(Session session) throws IOException
    {    
        if (managedSessions.contains(session)) {
            // working with preexisting session
        } else {
            managedSessions.add(session);
        }
    }

    @OnWebSocketClose
    public void onClose(Session session, int statusCode, String reason) 
    {
        managedSessions.remove(session);
    }

}

【讨论】:

  • 这有点跑题了,但这里的要求是不同的,它们是两个 HashMap,一个具有 machineId 键和值作为 Id 数组(即会话的唯一 Id),第二个是 Id 键和价值会议。因此,当使用第一个 hashmap 为机器接收数据时,我们将检索 id 数组并使用这些 id 使用第二个 hashmap 向每个会话发送消息,并在关闭时使用 id 从第二个映射中删除会话,并从第二个数组中删除该 id地图。
  • 我不明白需要两张地图。为什么不直接将机器 ID 链接到其关联的会话。例如。 Map&lt;MachineId,List&lt;Session&gt;&gt;Map&lt;MachineId,Set&lt;Session&gt;&gt;
  • 哦!谢谢!我从来没有放弃过,继续使用其他人先前系统版本的先前实现的方法
猜你喜欢
  • 2010-10-15
  • 1970-01-01
  • 2013-06-11
  • 2011-02-19
  • 2015-12-19
  • 1970-01-01
  • 1970-01-01
  • 2019-08-24
  • 1970-01-01
相关资源
最近更新 更多