首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EJB池与线程安全和@PreDestroy

EJB池与线程安全和@PreDestroy
EN

Stack Overflow用户
提问于 2015-08-26 15:17:58
回答 3查看 1.1K关注 0票数 5

我不明白EJB容器如何使用实例变量来管理@Stateless bean的线程安全。因此,在解释我所关注的问题之前,我会先举一个简单的例子:

代码语言:javascript
复制
@Stateless
public class BeanTest{

@Inject
private String var;

private Connection connection;

@Resource(name = "jdbc/TestDB")
private DataSource dataSource;

public void modify() {
    var = "TestName";
}

@PostConstruct
public void initialize() {
    try {
        connection = dataSource.getConnection();
    } catch (SQLException sqle) {
        sqle.printStackTrace();
    }
}

@PreDestroy
public void cleanup() {
    try {
        connection.close();
        connection = null;
    } catch (SQLException sqle) {
        sqle.printStackTrace();
    }
}
}

以下是我的问题,假设我们的容器支持池:

1.池与线程安全:

用户1使用了一个BeanTest实例并使用修改方法修改了var,然后他完成了操作,容器将BeanTest实例放在托管池中。当用户2试图为一个请求使用相同的bean时,可能得到由用户1修改的BeanTest的同一个实例(我知道这可能也会得到另一个实例)。那么,他将找到实例变量var的哪种状态(默认值是null还是"TestName")?如果是新修改的一个,这是否意味着即使@Stateless bean也不是100%线程安全的?因此,在线程安全方面,最终没有添加-value的容器,因为不使用实例变量可以使bean线程安全,即使它不是@Stateless bean

2.合用vs @PreDestroy

如果bean被返回到托管池,并且没有销毁,这是否意味着@Predestroy方法将不会被调用,在这种情况下,连接将保持打开?所以,如果我们在池中有30块豆子,我们可能有30个未被使用的开放连接,这不是一个性能问题吗?或者这不是@Predestroy与池结合的方式?(使用Connection只是一个例子,我们可能需要在@Predestroy中关闭其他类型的资源)

NB: --这不是一个真实的例子,所以我不是在寻找替代的解决方案,我关心的是理解整个概念,以及如何在Application中管理事情,在幕后发生了什么

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-08-27 05:46:03

我认为你所指的线程安全是非再介入条款。

容器供应商企业JavaBeans 3.2的责任,最终发布会话Bean组件合同2013年4月10日下午2:59 4.10.13不可重入实例容器必须确保在ly上一个线程可以在任何时候执行st无状态或有状态会话bean实例。因此,statef和无状态会话bean不必编码为可重入。此规则的一个含义是,应用程序不能对无状态或有状态会话bean实例进行回送调用。

您可以在无状态会话bean中忽略EJB编程限制,创建一堆线程并执行一些非线程安全的操作。集装箱不会阻止你的。这可能会由于线程管理冲突而导致各种错误。

容器只承诺每次只允许一个线程访问无状态ejb。(关于单身者有一些不同的规则)

您是对的,如果实例被返回到示例中的连接可以构建的池中。当然,因为被实例仍然存在。

如果深入应用服务器文档,即Glassfish EJB池调优章节,您将发现默认情况是销毁对象实例,而不是将它们返回池。JDBC连接也是如此,这些连接将被关闭和清理。重用是一种选择,在这种情况下,如果试图在SSB中创建状态,则可以消耗一些额外的内存。如果实例闲置在池中,则不会对性能产生太大影响。

确切的池实现取决于应用服务器供应商,只要他们遵守规范。我认为您会发现默认的行为是在使用后销毁实例。这会导致托管资源被清理。

但是所有这些都是静音的,在您的示例中,您试图在类中存储一个状态,连接字段。不需要在无状态组件中创建状态,这不是这种组件的用途。Java体系结构的其他部分处理状态。(实体、状态、JCA)

票数 2
EN

Stack Overflow用户

发布于 2015-08-26 17:54:34

1)容器保证线程安全,这意味着单个线程可以一次访问给定的SLSB。这与保证国家不会改变毫无关系。顺便说一句,在SLSB中拥有可变的状态是毫无意义的。

2)你不想在SLSB的有生之年保持一种联系,因为你实际上是在阻止它回到游泳池,冒着筋疲力尽的危险。

票数 2
EN

Stack Overflow用户

发布于 2015-08-26 15:36:00

  1. 如果注入的AnotherBean是无状态的,那么调用AnotherBean.setName()是没有意义的。如果它是statefull,那么在无状态bean中注入有状态bean是没有意义的(检查创建有状态bean的目的)。关于线程安全:容器不能使类线程本身安全,但它保证单个客户端线程一次使用特定的EJB实例(检查Chris的答案中的引号)。因此,如果您没有在EJB客户端的不同线程中使用EJB,那么通过使用线围,您的代码是线程安全的。
  2. 不要使用实例变量,然后在无状态bean中注入实例变量。否则,您与您的@Stateful注释不一致。因此,删除connection状态变量。无论如何,您不希望只为bean保持长时间的开放连接:每次从数据源获取连接。此外,不要忘记在使用连接后(在try/finally子句中)关闭连接。有了池,它就像JDBC连接池一样工作:当池/EJB容器决定不再需要实例时(例如,当它希望减少实例数量或抛出非应用异常时),那么将调用@PreDestroy方法。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32230502

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档