Несколько потоков, начинающих транзакцию в JUNIT - PullRequest
2 голосов
/ 16 декабря 2011

Я пытаюсь воспроизвести (и не полностью защищенный тест проблемы многопоточности) проблему с блоком потоков одним из моих методов, написав тестовый модуль. Так как я вижу множество случаев

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

в нашей среде с 2-мя серверами PROD я могу довольно легко воспроизвести в моем модульном тесте. Я пытался создать несколько потоков в моем методе 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 может иметь несколько активных потоков в любое время (и, следовательно, одноэлементный менеджер сущностей)?

Я что-то здесь упускаю?

Спасибо

1 Ответ

0 голосов
/ 16 декабря 2011

EntityManager не является потокобезопасным. Вот почему часто говорят, что вы не должны внедрять EntityManager в общие экземпляры, такие как сервлеты. Это четко задокументировано (JSR-317 стр. 286):

Менеджер сущностей не должен совместно использоваться несколькими выполнение потоков, так как менеджер сущностей и постоянный контекст не обязательно должен быть потокобезопасным. Менеджеры должны быть доступны только однопоточным.

...