不同的线程可以访问无状态EJB的特定实例的不同方法吗?

时间:2013-08-02 04:10:05

标签: multithreading java-ee thread-safety ejb stateless-session-bean

@Stateless
public class MyBean1 {

    pulic void method1() {
        //method implementation
    }

    pulic void method2() {
        //method implementation
    } 
}

考虑MyBean1的特定实例。然后我们知道多个线程不能同时访问method1()method2()。但是,虽然线程正在访问method1(),但是另一个线程可以访问method2()吗?

2 个答案:

答案 0 :(得分:3)

我认为ejb 3.1规范的第4.3.14节给出了答案。

  

4.3.14序列化会话Bean方法
  以下要求适用于无状态和有状态会话Bean。   有关Singleton会话bean并发要求,请参见第4.8.5节。

     

容器序列化对每个有状态和无状态会话bean实例的调用。   大多数容器将支持并发执行的会话bean的许多实例;   但是,每个实例只能看到序列化的方法调用序列。   因此,有状态或无状态会话bean不必编码为可重入。

     

容器必须序列化所有容器调用的回调   (即业务方法拦截器方法,生命周期回调拦截器方法,   超时回调方法,beforeCompletion等),它必须序列化这些回调   使用客户端调用的业务方法调用。

     

...

据我了解EJB规范,如果你想要对并发进行细粒度控制(bean托管,容器管理),你应该使用Singletons。

答案 1 :(得分:1)

让我们稍微修改你的例子

@Stateless
public class MyBean1 {
    @Resource
    private SessionContext sessionContext;

    pulic void method1() {
        // method implementation
        //   As a side-effect, something is written into a database
        //   using an XA data source,
        //   and a message is sent using XA JMS
        //   (both under control of an XA transaction)
    }

    pulic int method2(int i) {
        return i * i;
    } 
}

例如,会话上下文用于获取UserTransactiongetCallerPrincipal。它们不一定总是相同的(当两个客户端都是EJB时)。至于UserTransaction:这个绑定到当前线程(参见Javadoc)。

由于会话上下文存储在字段中(并且未向每个单独的方法传递参数),因此两个不同的客户端无法访问相同的EJB实例。

因此规范要求容器序列化调用到同一个实例。

如果你看一下method2,一个没有任何副作用的纯功能实现,就不需要EJB。