为什么要池化无状态会话Bean?

28

Java中的无状态bean在两次来自客户端的调用之间不保留其状态。因此,简而言之,我们可以将它们视为具有业务方法的对象。每个方法接受参数并返回结果。当调用该方法时,在执行堆栈中创建一些局部变量。当该方法返回时,局部变量从堆栈中删除,并且如果分配了一些临时对象,则会进行垃圾回收。

在我看来,这与通过单独的线程调用同一单个实例的方法没有区别。那么,为什么容器不能使用一个bean实例而不是池化多个bean呢?

5个回答

29

对象池有几个作用。

首先,通过每个实例只有一个bean,您可以确保线程安全(例如Servlets不是线程安全的)。

其次,您可以减少bean可能具有的任何潜在启动时间。虽然Session Beans是“无状态”的,但它们只需要与客户端无关的无状态。例如,在EJB中,您可以将多个服务器资源注入到Session Bean中。该状态对bean是私有的,但没有理由从调用到调用保留该状态。因此,通过汇集bean,您将仅在创建bean时减少这些查找。

第三,您可以使用bean池作为限流的一种手段。如果池中只有10个Bean,则最多只会有10个请求同时工作,其余请求将排队等待。


3
拥有每个实例一个豆子,可以保证线程安全(例如Servlet不是线程安全的)。在无状态会话bean中,如何确保线程安全有帮助? - anjanb
当你断言Servlets不是线程安全的时候,我不明白你的意思。如果我没记错的话,Tomcat管理控制台也允许我对Servlets进行池化。 - Alan
1
无状态会话Bean是简单的组件。它们可以拥有“状态”,但该状态与客户端无关,而是与组件相关。Bean具有完整的生命周期。因此,您可以在Bean中拥有本地缓存,而无需担心同步。 - Will Hartung
1
Tomcat可能提供Servlet实例池,但规范并不要求。您不能假设特定的servlet实例一次只能被单个请求访问。 - Will Hartung
6
开发人员需要编写一个线程安全的servlet,因为有多个线程同时访问它。无状态会话bean不需要编写成线程安全,因为容器已经保证了它是线程安全的(不会有多个线程同时执行;相反,有多个bean池)。 - Rob Whelan

1

池化提高性能。

一个单一实例处理所有请求/线程将导致很多争用和阻塞。

由于您不知道将使用哪个实例(并且几个线程可以同时使用单个实例),因此bean必须是线程安全的。

容器可以根据实际活动管理池大小。


1
Java EE模型的事务性使用线程上下文来管理事务生命周期。
这种简化存在是为了不必实现任何特定接口以直接与UserTransaction对象交互;当从InitialContext检索事务时(或将其注入会话bean),它会绑定到一个线程本地变量以供重复使用(例如,如果您的无状态会话bean中的方法调用另一个也使用注入事务的无状态会话bean)。

0
无状态会话Bean的生命周期包括不存在、被动和方法就绪(被动或非活动)状态。为了优化性能,容器通过ejbActivate()和ejbPassivate()回调在活动状态和被动状态之间管理bean,从而管理bean池,而不是从创建到方法就绪状态遍历bean。
sreenut

0

方法本质上是线程安全的(包括静态方法)。为什么?很简单,因为方法内部的每个变量都是在堆栈内存中创建的,即方法内部使用的每个变量都是每次调用时创建的(它不是共享的)。但是,参数不属于堆栈。

然而,如果方法使用了不安全的变量,则该方法是不安全的:

a)调用静态字段或变量。但是,在每种情况下都会发生这种情况。

b)调用共享资源。例如EntityManager。

c)传递不安全的参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接