当前位置: 首页 > 知识库问答 >
问题:

我应该使用Java字符串池进行基于唯一客户ID的同步吗?

亢仰岳
2023-03-14
public class Key {
    private String id;

    public Key(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ( (id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        Key other = (Key)obj;
        if (id == null) {
            if (other.id != null) return false;
        } else if (!id.equals(other.id)) return false;
        return true;
    }
}

Interner<Key> myIdInterner = Interners.newWeakInterner();

public void processApi1(String clientUniqueId, RequestType1 request) {
    synchronized(myIdInterner.intern(new Key(clientUniqueId))) {
        // code to process request
    }
}

public void processApi2(String clientUniqueId, RequestType2 request) {
    synchronized(myIdInterner.intern(new Key(clientUniqueId))) {
        // code to process request
    }
}

共有1个答案

曹经业
2023-03-14

如果您的字符串足够唯一(例如,通过密码哈希1)生成),那么在客户端ID上进行同步可能会起作用,只要您首先对它们调用string.intern()。由于ID是唯一的,您不太可能遇到与其他模块冲突的情况,除非您碰巧将ID传递给它们,并且它们遵循了锁定它们的不良做法。

这就是说,这可能是个坏主意。如果其他人锁定同一string实例,那么有一天可能会出现不必要的争用,除此之外,主要的问题是您必须intern()所有string对象,而且由于string intern表的本机实现、它的大小是固定的等原因,这通常会导致性能较差。如果您真的需要仅基于string进行锁定,那么最好使用Guava的Interners.NewWeakInterner()interner实现,这样可能会有更好的性能。将字符串包装在另一个类中,以避免在内置的string锁上发生冲突。关于这种方法的更多细节,请参阅本答案。

除此之外,通常还有另一个自然对象要锁定,比如会话对象中的锁等等。

这与这个问题很相似,因为这个问题的答案更充实。

1...或者,至少有足够的位,使冲突的可能性足够小,并且如果您的客户端ID不是您的攻击面的一部分。

 类似资料:
  • 我使用而不是,当我验证为 我得到 SQLSTATE[42S22]:未找到列:1054“where子句”中的未知列“id”(SQL:选择count(*)作为来自

  • 问题内容: 我正在对现有的Java软件进行内存分析。在oql中是否存在等效的sql’group by’,以查看具有相同值但不同实例的对象的数量。 通过s.toString()从java.lang.String的组中选择count(*) 我想获得一列重复的字符串以及重复的数量。这样做的目的是查看大量的案例,以便可以使用String.intern()对其进行优化。 例: 等等… 问题答案: 以下内容基

  • 这是我所拥有的:我们有2个应用程序,一个生产和一个消费。两者都运行在不同的JVM上。它们向持久主题发送消息,并使用相同的ClientId。 我想知道在JMS 2.0规范下是否允许这样做,以及在Artemis中这样做是否可以。 在消费方面,我有一个连接工厂 在实例化ActiveMQConnectionFactoryBean时,我通过以下方法在工厂上设置clientID:<code>。setClien

  • 问题内容: 由于我没有收到对最后一个问题的肯定回答。我将尝试自己编写一个Java FTP上传小程序。 我的问题是:“您能推荐一个Java FTP客户端库供我使用吗?” 我希望它是: 稳定 能够处理被动和主动模式 能够提供上传进度信息 如果出了问题(尤其是上传不成功时),则引发可捕获的异常 便宜/免费使用,最好是开源的 我发现这个 概述了一些库,但由于这篇文章是从2003年,也许一些新的事态发展已经

  • 问题内容: 这与Java字符串常量池有关。在我的一个程序中,我正在解密数据库的密码并将其存储在字符串中。我听说Java字符串将存储在Constant池中,并且不会被VM重新启动或加载了String Quits的ClassLoader破坏。 如果是这种情况,我的密码将存储在字符串池中。我非常关心这个问题。还有其他方法可以销毁这些文字或我可以做的其他任何事情。 请对此提出建议, 问候,阳光明媚。 问题

  • 我的问题是对称解密。而不是非对称解密。所以正确的答案是在这里只在Java中用密码短语解密PGP加密的文件 我使用gpg加密“Hello”: