2

仮想センターに接続してデータを取得する必要があるシナリオがあります。同時アクセスの問題があるため、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つの同時要求がある場合、そのうちの1つが「セッションが認証されていません」と言って失敗します。問題に対処するためのより良い方法で私たちを助けてくれませんか。また、同じインスタンスが常に使用されるため、仮想センターが異なるかどうかをどのように区別できますか。

4

2 に答える 2

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();
         }
    }
}
于 2012-10-17T17:21:08.350 に答える
0

あなたのシーケンス

  1. 接続
  2. 何かをする
  3. 切断する

アトミックではありません。つまり、可能性があります。

  1. スレッド 1 接続
  2. スレッド 2 接続
  3. スレッド1は何かをします
  4. スレッド 1 の切断
  5. スレッド 2 は何かをしようとして失敗します。

クライアントが接続に失敗したり、切断に失敗したり、操作を別のクライアントとインターリーブしたりできないように、クラスを構成します。

あなたの API は、接続を使用したいコードが、接続中に接続を使用するオブジェクトを渡すことを許可し、その接続を使用した結果を返します。

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

そして、代わりにaを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 に答える