オンデマンドで VPN 接続を開始するシングルトン Bean を Java EE に実装したいと考えています。
したがって、次のようなクラスを作成しました。
@Singleton
class VPNClient{
private boolean connected;
@Lock(LockType.READ)
public boolean isConnected(){
return this.connected;
}
@Asynchronous
@Lock(LockType.WRITE)
public void connect(){
// do connect, including a while loop for the socket:
while(true){
// read socket, do stuff like setting connected when VPN successfully established
}
}
}
次に、VPN 接続を要求し、それを作成しようとする別の Bean があります。
class X {
@Inject
VPNClient client;
private void sendStuffToVPN(){
// call the async connect method
client.connect();
// wait for connect (or exception and stuff in original source)
while(!client.isConnected()){
// wait for connection to be established
Thread.sleep(5000);
}
}
}
私の問題は、接続が破棄されるまで終了しない接続メソッドのために、それが持っている書き込みロックが isConnected() へのすべての読み取りをブロックすることです。
[アップデート]
これはうまくいけば問題を説明するはずです:
- スレッド 1 (Bean X) がスレッド 2 (Singleton Bean VPNClient) を呼び出す .connect()
- 現在、シングルトン Bean VPNClient に無限の書き込みロックがあります。しかし、メソッドは非同期と呼ばれていたためです。スレッド 1 は次のように進みます。
- スレッド 1 (Bean x) はスレッド 2 (VPNClient.isConnected()) を呼び出そうとしますが、(connect() で開始された) 書き込みロックの解放を待たなければなりません。
- その後、J2EE コンテナはタイムアウトになるまで待機したため、javax.ejb.ConcurrentAccessTimeoutException をスローします。
この種の同時実行性の問題を解決するための適切なパターンはありますか?