【问题标题】:Using Java Singleton instance in a multi threaded environment在多线程环境中使用 Java Singleton 实例
【发布时间】:2019-05-21 06:59:09
【问题描述】:

我的应用程序想要与 REST 服务器通信。首先,我们需要进行身份验证,作为响应,我们将收到一个客户端令牌。此令牌的有效期为 30 分钟,对于其余的通信,此客户端令牌需要作为标头存在。

我计划实现一个处理 REST 通信的单例类。不遵循 ENUM 方法(如许多其他线程中提到的)的原因是因为需要在运行时进行休息调用并填充客户端令牌。

public class RESRService {

    private static RESRService RESTSERVICEINSTANCE;
    private String clientToken;

    private RESRService(){
        clientToken = //make a rest call to authenticate and get the client 
                      //token from reponse
    }

    public static RESRService getInstance(){
        if(RESTSERVICEINSTANCE == null){
            RESTSERVICEINSTANCE = new RESRService();
        }

        return RESTSERVICEINSTANCE;
    }

    public void makeRestCall(String requestSpecificInfo){
        //set client token to header
        //create JSON body using requestSpecificInfo
        //make rest call
    } 

}

这里的主要挑战是这个类将被多个线程同时使用(客户端令牌对于所有线程都是相同的)。我的疑问是关于我们进行 REST 调用以填充客户端令牌的初始化部分。如果 REST 调用需要几秒钟来设置客户端令牌,线程之间是否存在歧义的可能性。如果是,您认为实现这一点的最佳方式是什么?

【问题讨论】:

    标签: java multithreading singleton


    【解决方案1】:

    如果你有一个多线程应用并且使用单例模式,你可以使用 synchronized 关键字。

    public static synchronized RESRService getInstance(){}
    

    但是 getInstance() 方法是同步的,所以它会导致性能下降,因为多个线程不能同时访问它并且所有操作都是同步的。所以你可以使用Double checked locking 解决方案。

    private static volatile RESTSERVICE RESTSERVICEINSTANCE;
    
    public static RESTSERVICE getInstance(){
        RESTSERVICE restservice = RESTSERVICEINSTANCE;
        if(restservice == null){
            synchronized (RESTSERVICE.class){
                restservice = RESTSERVICEINSTANCE;
                if(restservice == null){
                    restservice = new RESTSERVICE();
                }
            }
        }
        return restservice;
    }
    

    【讨论】:

    • 谢谢@Turac。让我试试看。在此之前,你能告诉我我的实现方式有什么问题吗?我之所以选择这种逻辑是有充分理由的,而不是简单地遵循一种广泛使用或最适合这种情况的模式,这只是为了我的内心满足。
    • 别说了。这里有很好的解释(en.wikipedia.org/wiki/Double-checked_locking)。谢谢
    • 一次更正。除非我们更新 volatile 变量,否则其他线程可能看不到它。 if(restservice == null){ RESTSERVICEINSTANCE = restservice = new RESTSERVICE(); }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    相关资源
    最近更新 更多