如何正确处理并发?
How to correctly deal with concurrency?
我正在使用 JavaEE 构建 REST API。我正在使用 TomEE 作为应用程序服务器。我有一个 Singleton
JPA DAO 来处理 Postgres 数据库和 Stateless
服务来为我的 RESTfull class 提供方法,它有 GET
、POST
和 DELETE
方法。到目前为止,我一直在使用 rest assured 来测试我的 url 路线。一切正常,但我想强调我的系统,所以我这样做了:
Runnable r1 = () -> {
for (int i = 0; i < 10; i++) {
RegisterAndLogService service = new RegisterAndLogService();
//lots of service calls
}
};
Runnable r2 = () -> {
for (int i = 0; i < 10; i++) {
RegisterAndLogService service2 = new RegisterAndLogService();
//lots of service calls
}
};
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
但是当我的一个线程开始第二次迭代时,我得到了这个:
java.lang.IllegalStateException: Transaction already active
我怎样才能堆积 Dao 请求并一次一个地正确处理它们,等待当前事务完成? EJB/JPA 能以某种方式参与其中吗?保存请求并尽快处理它们?
很难理解你在这里做什么,你问的问题是在测试代码中还是在测试中的API ...或者[=48=后面的东西].
但是如果你得到一个 "Transaction already active",这意味着 某事 正在做类似的事情:
- 尝试使用具有多个线程的单个 JPA 事务管理器(不要),
- 尝试在同一个线程上同时进行多个事务(不要),或者
- 不清理(提交或回滚)事务。
在最后一种情况下,寻找可以通过异常从负责事务的代码区域"escape"而不回滚的情况。
我建议您查看您一直在使用的 JPA 文档,以确保您了解事务、事务管理器和线程之间的关系。
I believe my case is the first one - trying to use a single JPA transaction manager with multiple threads. Is there any design pattern or good practice about keeping a single JPA transaction manager while have lots of instances of stateless beans being requested?
唯一可行的方法是让每个线程都有自己的事务管理器。要么每个线程必须以编程方式创建(和释放)自己的 TM,要么您依赖框架来执行此操作;例如按照各种注释的指示。
TM 对象设计为轻量级(即实例化成本低)和非线程安全。你不应该跨线程共享它们1,你不应该需要回收它们。
1 - ...除非您有一个 需要 跨多个线程的 JPA 事务。为此,有 "ways to do it".
我正在使用 JavaEE 构建 REST API。我正在使用 TomEE 作为应用程序服务器。我有一个 Singleton
JPA DAO 来处理 Postgres 数据库和 Stateless
服务来为我的 RESTfull class 提供方法,它有 GET
、POST
和 DELETE
方法。到目前为止,我一直在使用 rest assured 来测试我的 url 路线。一切正常,但我想强调我的系统,所以我这样做了:
Runnable r1 = () -> {
for (int i = 0; i < 10; i++) {
RegisterAndLogService service = new RegisterAndLogService();
//lots of service calls
}
};
Runnable r2 = () -> {
for (int i = 0; i < 10; i++) {
RegisterAndLogService service2 = new RegisterAndLogService();
//lots of service calls
}
};
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
但是当我的一个线程开始第二次迭代时,我得到了这个:
java.lang.IllegalStateException: Transaction already active
我怎样才能堆积 Dao 请求并一次一个地正确处理它们,等待当前事务完成? EJB/JPA 能以某种方式参与其中吗?保存请求并尽快处理它们?
很难理解你在这里做什么,你问的问题是在测试代码中还是在测试中的API ...或者[=48=后面的东西].
但是如果你得到一个 "Transaction already active",这意味着 某事 正在做类似的事情:
- 尝试使用具有多个线程的单个 JPA 事务管理器(不要),
- 尝试在同一个线程上同时进行多个事务(不要),或者
- 不清理(提交或回滚)事务。
在最后一种情况下,寻找可以通过异常从负责事务的代码区域"escape"而不回滚的情况。
我建议您查看您一直在使用的 JPA 文档,以确保您了解事务、事务管理器和线程之间的关系。
I believe my case is the first one - trying to use a single JPA transaction manager with multiple threads. Is there any design pattern or good practice about keeping a single JPA transaction manager while have lots of instances of stateless beans being requested?
唯一可行的方法是让每个线程都有自己的事务管理器。要么每个线程必须以编程方式创建(和释放)自己的 TM,要么您依赖框架来执行此操作;例如按照各种注释的指示。
TM 对象设计为轻量级(即实例化成本低)和非线程安全。你不应该跨线程共享它们1,你不应该需要回收它们。
1 - ...除非您有一个 需要 跨多个线程的 JPA 事务。为此,有 "ways to do it".