2012-10-17 52 views
2

我有一个场景,我必须连接到虚拟中心并获取数据。我实现了一个单例类,以便两个线程不能同时访问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个同时请求获得来自viruatal中心的数据,其中一人失败说“会话未通过身份验证”。 你能帮助我们以更好的方式来处理这个问题吗?因为总是使用相同的实例,我们如何区分不同的虚拟中心。

+1

你做得完全错误,不要使用单身,如果你不能 –

+0

换句话说就是@RomanC说的。 –

+0

阅读:https://sites.google.com/site/steveyegge2/singleton-considered-stupid –

回答

0

你的序列

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

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

  1. 线程1连接
  2. 线程2连接
  3. 线程1做的东西
  4. 线程1断开
  5. 线程2次尝试做的东西和失败。

结构类以便客户端无法连接失败,不能断开,或与另一交错操作。

你的API可以使想要使用一个连接在使用,而它连接的连接对象通过,并返回使用该连接的结果代码:

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

,然后代替getInstanceuseConnection,做

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

,使connectdisconnectprivate,使客户端不能滥用它们。

0

您只保留对第一种方法的连接的独占访问权限。

我建议你添加一个Lock,比如ReentrantLock,你在第一个方法中锁定并在释放连接时解锁。

另一种方法是使用可能更安全的访客模式。

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