0

オンデマンドで 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 をスローします。

この種の同時実行性の問題を解決するための適切なパターンはありますか?

4

2 に答える 2

0

@Lock(LockType.WRITE) は、呼び出し元が @Asynchronous 経由で移動した場合でも、呼び出されたメソッドが完了するまで、シングルトン Bean 内のすべてのメソッドをロックします。

考えてみれば、これは正しい動作です。処理がまだ進行中の場合、Bean への他のメソッド呼び出しから並行性の問題が発生する可能性があります。

これを回避する方法は、シングルトンに @ConcurrencyManagement(ConcurrencyManagementType.BEAN) を設定して、同時実行性と接続へのアクセスのロックを自分で処理することです。

概要については、 http://docs.oracle.com/javaee/6/tutorial/doc/gipvi.html#indexterm-1449をご覧ください。

于 2013-06-05T06:45:12.107 に答える
-1

これを試して。

 class X {
    private void sendStuffToVPN(){
      VPNClient client = new VPNClient();

      // call the async connect method
      new Thread(new Runnable(){
                    public void run()
                    {
                       client.connect();
                    }
      }).start();

      // wait for connect (or exception and stuff in original source)
      while(!client.isConnected()){

        // wait for connection to be established
        Thread.sleep(5000);
      }
    }
  }
于 2013-06-03T10:20:39.097 に答える