【问题标题】:Could I have thread safety problems using this aproach?使用这种方法会有线程安全问题吗?
【发布时间】:2012-01-07 20:09:42
【问题描述】:

我正在使用 EJB/JPA,并且我创建了一个名为 createDataset 的静态方法,它将查找 Dataset 对象。每次我必须插入、更新、删除等实体时,我都会检索一个调用 DatasetFactory.createDataset() 的 DatasetObject 并调用适当的方法(插入、更新等)。

代码:

public class DatasetFactory {
    public static Dataset createDataset() {
        try {
            return (Dataset) new InitialContext().lookup("java:global/.../Dataset");
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

public interface Dataset<T> {
    void insert(T entity);
    //...
}

@Stateless
@EJB(name = "java:global/.../Dataset", beanInterface = Dataset.class)
public class DatasetBean<T> implements Dataset<T> {

    @PersistenceContext(type = PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;

    @Override
    public void insert(T entity) {
        entityManager.persist(entity);
    }
    //...
}

使用这种方法我会遇到线程安全问题吗?如果是这样,我应该做哪些修改?我应该将 synchronized 修饰符放在 DatasetFactory.createDataset() 中吗?

非常感谢!

【问题讨论】:

    标签: java hibernate jpa thread-safety ejb


    【解决方案1】:

    您不必同步 EJB 的任何方法,因为 EJB 规范指定 EJB 实例不能被两个并发线程调用。 EJB 容器为您处理同步和线程安全。这是使用 EJB 的要点之一。

    【讨论】:

      【解决方案2】:

      从线程安全的角度来看,您的代码看起来不错。

      但是看起来您正在实现一个 DAO(数据访问对象),只是您将 DAO 称为数据集,并且使用 EJB 实现 DAO 并不是一个好主意,因为 EJB 容器会在启动时加载并验证您的所有 EJB这会减慢速度。通常 EJB 只在内存(EJB 池)中保留一定数量的 EJB,但如果您不将 DAO 实现为 EJB,您可以根据需要创建任意数量的 EJB,Java 的 GC 会为您清理它们。

      【讨论】:

      • @joaosavio 如果您将容器配置为,例如,最多创建 5 个 bean 实例,但超过 5 个用户同时使用您的应用程序,您可能会遇到一些性能问题(饥饿)。但是,我在回答中提到的是,当您的应用服务器启动时,它应该创建并验证您的所有 EJB,这会减慢“启动时间”,而不是降低正在运行的应用程序的性能。跨度>
      【解决方案3】:

      如果您的实体管理器是线程保存的,那么使用您的插入方法没有风险

      【讨论】:

      • entityManager 不是线程安全的,但是 EJB 可能永远不会被两个当前线程调用,所以这不是问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      • 1970-01-01
      • 2017-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多