3

さまざまなJavaクライアント用にRMIベースのデータサービスサーバーを設計しています。クライアントはRMIを使用してリモートでCRUD操作を実行し、サーバーのORMにはJPAを使用する予定です。

一部のRMIは、実装がスレッドセーフであることを要求していることを知っているので、EntityManagerusingを注入することを計画してい@PersistenceContextます。2つの質問があります。

  1. スプリングはEntityManager注入されたスレッドを安全にしますか、それとも必要に応じて注入EntityManagerFactoryして呼び出すcreateEntityManager必要がありますか?
  2. メソッドコードがスレッドセーフであることが保証されている場合でも、同期を確認する必要がありますか?

RMI仕様による

  1. リモートリクエストが着信すると、メソッド呼び出しをカプセル化するリクエストオブジェクトにすぐにデマーシャルされます。RemoteCallインターフェースを実装するクラスのインスタンスであるこの要求オブジェクトには、ソケットの出力ストリームへの参照があります。つまり、RMIはソケットを共有しますが、ソケットは一度に1つのリモートメソッド呼び出しにのみ使用されます。
  2. ソケットからリクエストを受け取ったスレッドは、メソッド呼び出しの対象となるリモートオブジェクトを見つけ、そのリモートオブジェクトに関連付けられているスケルトンを見つけ、そのスケルトンのdispatch()メソッドを呼び出します。ディスパッチメソッドには次の署名があります。
  3. public void dispatch(java.rmi.Remote obj、java.rmi.server.RemoteCall call、int opnum、long hash)はjava.lang.Exceptionをスローします
  4. スケルトンのdispatch()メソッドは、サーバー上で適切なメソッドを呼び出します。これは、あなたが書いたコードが実際に実行される場所です。
  5. serverメソッドは値を返し、最終的には元の要求が受信されたソケットを介して伝播されます。

プロセス定義は、コードの多くの分離された呼び出しスタックがRMI環境で作成される可能性があることを示唆していると思います。したがって、RMIではコードがスレッドセーフである必要がありますね。

4

2 に答える 2

3

RMIを介してオブジェクトをエクスポートする場合、オブジェクトのクライアントが1つしかない場合でも、複数のスレッドを処理する必要があります。その理由は次のとおりです。リモートオブジェクトを作成するスレッドは、リモート呼び出しを処理するスレッドとは明らかに異なります。

したがってEntityManager、リモートオブジェクトの作成中にインジェクトすると、リモート呼び出し中に使用されたスレッドとは異なるスレッドにインジェクトされます。ただし、anEntityManagerは単一のスレッド、より具体的には作成されたスレッドでのみ使用できます。たとえば、HibernateEntityManagerの場合、これが当てはまらない限り、は機能しません。

したがって、を使用してオンデマンドEntityManagerFactoryで作成する必要があります。EntityManager作成を最小限に抑えるために、EntityManagerをに保存できます。EntityManagerThreadLocal

于 2013-02-28T10:26:34.490 に答える
0

RMIでは、コードがスレッドセーフである必要があります。

奇妙なことに、コメントですでに回答されている質問をしているのですが、上記で引用した内容に関係なく、RMI仕様#3.2には、次のように正確に記述されたはるかに短い部分があります。

「リモートオブジェクトの実装では、その実装がスレッドセーフであることを確認する必要があります。」

于 2013-03-01T07:11:30.560 に答える