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 个同时请求从虚拟中心获取数据,其中一个请求失败,说“会话未通过身份验证”。你能帮助我们更好地处理这个问题吗?并且由于始终使用相同的实例,如果它是不同的虚拟中心,我们如何区分。

4

2 回答 2

0

你的序列

  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 private以便客户不能滥用它们。

于 2012-10-17T17:15:01.190 回答
0

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

我建议您添加一个您在第一种方法中锁定并在释放连接时解锁的Locklike 。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();
         }
    }
}
于 2012-10-17T17:21:08.350 回答