繁体   English   中英

从另一个班级访问的Singleton班级

[英]Singleton class accessed from another class

我有一个场景,我必须连接到虚拟中心并获取数据。 我实现了一个单例类,以使两个线程无法同时访问VC,因为它带来了并发访问问题。 我的代码如下:

public class Connector {    
private static Connector instance ;    
private Connector(String urlStr, String username, String password) {
    connect(urlStr, username, password);
}    
public static synchronized Connector getInstance(String urlStr, String username, String password) {
    if (instance == null){
        instance = new Connector(urlStr,username,password);
        System.out.println("creating instance");
    }
    return instance ;
}   
public void connect(String urlStr, String username, String password) {
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    try {
        //code to connect to VC
        }

    } catch (RuntimeException e) {
        connectException = e;
    } finally {
        Thread.currentThread().setContextClassLoader(cl);
    }
}


public void disconnect() throws RuntimeFault, RemoteException {
    //code for disconnect
    }
}

}

我通过以下方式从另一个类中调用了此方法:

Connector c = Connector.getInstance(dburl, dbuser, dbpass);
c.connect(dburl, dbuser, dbpass);
//code for getting data
c.disconnect();

现在,如果我有2个同时请求从虚拟中心获取数据的请求,则其中一个失败说“会话未通过身份验证”。 您能否帮助我们以更好的方式解决此问题。 并且由于始终使用同一实例,因此如果它是不同的Virtual Center,我们如何区分。

您的顺序

  1. 连接
  2. 做东西
  3. 断开

不是原子的,这意味着有可能

  1. 线程1连接
  2. 线程2连接
  3. 线程1做东西
  4. 线程1断开连接
  5. 线程2尝试执行操作并失败。

构造您的类,以使客户端不会失败,无法断开连接或与其他操作交错。

您的API可以允许想要使用连接的代码传入在连接时使用连接的对象,并返回使用该连接的结果:

 public interface ConnectionTask<T> {
   public T useConnection(Connection c);
 }

然后代替getInstance编写一个useConnection

 public synchronized <T> T useConnection(ConnectTask<T> c) {
   connect();
   try {
     return c.useConnection(this);
   } finally {
     disconnect();
   }
 }

并将connectdisconnect connect disconnect private这样客户端就不会滥用它们。

您仅在第一种方法中保留对连接的独占访问。

我建议您添加一个类似ReentrantLockLock ,您可以使用第一种方法进行锁定,并在释放连接时将其解锁。

另一种方法是使用更安全的访问者模式。

interface UsesConnector {
    public void useConnector(Connector connector);
}

public class Connector {
    private static final Connector connector = new Connector();

    public static synchronized void useConnector(String urlStr, String username, String password, UsesConnector usesConnector) {
         connector.connect(urlStr, username, password);
         try {
             usesConnector.useConnector(connector);
         } finally {
             connector.disconnect();
         }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM