在传统的n层Web应用程序中,用于web层的servlet和用于biz层的ejbs(2.0),使servlet模型成为多线程并且ejb模型单线程的原因是什么? 即所有请求只有一个servlet实例,但对于ejbs,对于每个请求,都有一个从bean池分配的新bean实例。
答案 0 :(得分:2)
确实只有一个特定Servlet
的实例,因为它们应该是无状态的。在实践中,情况并非总是如此,但也是如此。
但是有Stateless session beans
(SLSB)的多个实例,并且这些实例是合并的。
根据他们的定义,stateless session beans
是无国籍的,所以从表面来看,似乎就像一个悖论。问题是虽然stateless session beans
对于向他们发出的个别呼叫是无国籍的,但他们实际上经常有状态。
此状态采用对其他资源的引用的形式。 JPA entity manager
是不线程安全的,这是一个很好的例子。在单次调用stateless session bean
期间,调用者必须具有对此资源的独占访问权限。当呼叫返回时,下一个呼叫者可以拥有独占访问权等。
如果使用单个实例,则所有调用者都必须彼此等待(这当然会导致性能下降),或者他们可以同时访问此单个实例。在后一种情况下,bean实现者必须手动锁定非线程安全资源,如entity manager
,这通常很脆弱,容易出错,最终仍会导致调用者彼此等待。
因此,为了提高性能并仍然有安全保障,正在使用多个实例。
然后将这些实例合并并重新使用,而不是为每个请求创建新的实例,因为查找,初始化和注入bean的所有必需依赖项可能非常耗时。
所有这一切自动也意味着如果您将实体管理器或其他非线程安全资源注入Servlet(允许),您可能会遇到问题。这是Java EE体系结构中的一个小环洞,当然可以通过简单地使用无状态会话bean来轻松解决。
答案 1 :(得分:0)
我认为通常servlet为EJB中实现的繁重逻辑提供了薄外观。 Servlet应该是无状态的,因此没有理由创建同一个servlet的多个实例。
如果您只使用无状态bean,我认为没有理由拥有多个实例。但是有状态的EJB具有状态,因此每个同时请求需要实例。
我希望我没有说废话。