在多线程环境中使用Java Singleton实例

时间:2019-05-21 06:59:09

标签: java multithreading singleton

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

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

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调用花费几秒钟来设置客户端令牌,那么线程之间是否有可能出现歧义。如果是,您认为实现此目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

如果您有多线程应用程序并使用单例模式,则可以使用synced关键字。

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