3

我正在为不同的 Java 客户端设计一个基于 RMI 的数据服务服务器。客户端使用 RMI 远程执行 CRUD 操作,我计划将 JPA 用于服务器的 ORM。

据我所知,一些 RMI 请求实现是线程安全的,所以我打算注入EntityManagerusing @PersistenceContext. 我有两个问题。

  1. spring 是否使EntityManager注入的线程安全,或者我应该在必要时注入EntityManagerFactory和调用createEntityManager
  2. 当方法代码保证是线程安全的时,我是否还必须确保同步?

根据 RMI 规范

  1. 当一个远程请求进来时,它立即被解组为一个封装了方法调用的请求对象。此请求对象是实现 RemoteCall 接口的类的实例,它具有对套接字输出流的引用。这意味着,尽管 RMI 共享套接字,但一个套接字一次仅用于一个远程方法调用。
  2. 从套接字接收请求的线程找到方法调用的预期远程对象,找到与该远程对象关联的框架,并调用该框架的 dispatch() 方法。dispatch 方法具有以下签名:
  3. 公共无效调度(java.rmi.Remote obj,java.rmi.server.RemoteCall 调用,int opnum,长哈希)抛出 java.lang.Exception
  4. 骨架的 dispatch() 方法调用服务器上的正确方法。这是您编写的代码实际执行的地方。
  5. 服务器方法返回一个值,该值最终通过接收原始请求的套接字传回。

我认为流程定义表明我们可以在 RMI 环境中创建许多独立的代码调用堆栈。因此,RMI 要求代码是线程安全的,对吗?

4

2 回答 2

3

当您通过 RMI 导出对象时,它必须处理多个线程,即使您只有一个用于该对象的客户端。原因如下:创建远程对象的线程与处理远程调用的线程肯定不同。

因此,如果您EntityManager在创建远程对象期间注入 ,它将被注入到与远程调用期间使用的线程不同的线程上。但是,EntityManager只能在单个线程上使用,更具体地说,只能在创建它的线程上使用。例如,使用 Hibernate,EntityManager除非是这种情况,否则您将无法工作。

所以你必须使用 anEntityManagerFactory来创建EntityManager按需。为了尽量减少EntityManager创作,您可以EntityManagerThreadLocal.

于 2013-02-28T10:26:34.490 回答
0

RMI 要求代码是线程安全的,对吗?

奇怪的是,您所问的问题已经在评论中得到了回答,但是无论您在上面引用了什么,RMI 规范 #3.2中都有一个更短的部分准确地说明了这一点:

“远程对象实现需要确保其实现是线程安全的。”

于 2013-03-01T07:11:30.560 回答