多线程在 JUNIT 中启动事务

发布于 2024-12-21 06:03:48 字数 1053 浏览 3 评论 0原文

我试图通过编写单元测试来重现(而不是完全测试多线程问题)我的方法之一中的线程块问题。由于我在 2 服务器 PROD 环境中看到了大量实例

org.hibernate.exception.LockAcquisitionException: could not execute update query

,因此我应该能够在单元测试中相当轻松地重现。 我尝试在 JUnit 方法中生成多个线程,并且每个线程都调用我的方法。我一开始尝试使用 2 个线程。

ExecutorService exec = Executors.newFixedThreadPool(16);
    for (int i = 0; i < 2; i++) {
        exec.execute(new Runnable() {
             public void run() {
                 System.out.println("who is running: " + Thread.currentThread().getId());
                 em.getTransaction().begin();
                //do something()
                 em.getTransaction().commit();
             }
        });
    }

我收到错误:

Exception in thread "pool-1-thread-2" who is running: 11
java.lang.IllegalStateException: Transaction already active
at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:35)

它不允许我为第二个线程创建事务,并出现错误“事务已处于活动状态”。我认为 EntityManager 在任何给定时间都可以有多个活动线程(因此是一个单例实体管理器)?

我在这里错过了什么吗?

谢谢

I am trying to reproduce (and not fullproof test the multithreading issue) the thread block issue in one of my methods by writing a unit test. Since I see plenty of instances of

org.hibernate.exception.LockAcquisitionException: could not execute update query

in our 2 server PROD environment, I should be able to reproduce fairly easily in my unit test.
I tried to spawn multiple threads within my JUnit method and each thread invoking my method. I tried with 2 threads to begin with.

ExecutorService exec = Executors.newFixedThreadPool(16);
    for (int i = 0; i < 2; i++) {
        exec.execute(new Runnable() {
             public void run() {
                 System.out.println("who is running: " + Thread.currentThread().getId());
                 em.getTransaction().begin();
                //do something()
                 em.getTransaction().commit();
             }
        });
    }

I get an error:

Exception in thread "pool-1-thread-2" who is running: 11
java.lang.IllegalStateException: Transaction already active
at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:35)

It is not letting me create Transaction for the second thread with an error 'Transaction is already Active'. I thought EntityManager could have multiple Active Threads present at any given time ( and hence a singleton entitymanager)?

Am I missing something here?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心安伴我暖 2024-12-28 06:03:48

EntityManager 不是线程安全的。这就是为什么经常有人告诉您不应将 EntityManager 注入到 Servlet 等共享实例中。有明确记录(JSR-317 第 286 页):

实体管理器不得同时在多个实体之间共享
执行线程,因为实体管理器和持久性上下文是
不需要线程安全。实体管理器只能被访问
以单线程方式。

EntityManager is not thread-safe. That's why it is often told that you should not inject EntityManager to shared instances like Servlets. It is clearly documented (JSR-317 page 286):

An entity manager must not be shared among multiple concurrently
executing threads, as the entity manager and persistence context are
not required to be threadsafe. Entity managers must only be accessed
in a single-threaded manner.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文