一个被TransactionAttributeType.REQUIRES_NEW注释的方法会在新线程上运行吗?

3
根据文档,在容器管理的事务中,如果一个方法被注解为TransactionAttributeType.REQUIRES_NEW,它将暂停任何客户端事务,将调用委托给此方法/创建一个新的事务,并在新的事务完成后恢复之前的事务。
因此,这实际上意味着没有创建新线程,并且之前的事务处于“等待”状态,直到新的事务完成为止?
2个回答

2
Java-Doc所述:
如果客户端使用事务上下文调用,则容器会在启动新事务并调用方法之前暂停将事务上下文与当前线程关联。在方法和新事务完成后,容器会恢复暂停的事务关联。
它不是放弃线程或创建新线程,只是释放与事务的关联并在之后重新创建。如果它会创建一个新的线程,那么就没有必要删除关联,因为它从来没有建立过。

这意味着旧的交易被阻塞/等待,直到新的交易完成,对吗? - user4865748
1
一旦新的交易完成,它将会继续。 - Dennis Kriechel
1
只是提一下一个常见的误解:如果有挂起的事务,它可能是可能的或者高度可能的,将不会在方法返回后“看到”由“REQUIRES_NEW”事务所做的任何更改。 - aschoerk

2

容器管理的事务指的是JTA,而JTA规范不允许跨越多个线程的事务。每个JTA事务都与执行线程相关联,这意味着在任何给定时间最多只能有一个事务处于活动状态。请注意,可以将多个事务与单个线程关联,但是再次强调,在任何给定时间只能有一个事务处于活动状态。

由于JTA不支持嵌套事务,因此如果一个事务处于活动状态,则不可能在同一线程中启动另一个事务,直到第一个事务提交或回滚(或超时并再次回滚),从而释放当前线程的事务关联。

当使用事务属性REQUIRES_NEW的方法在事务上下文中被调用时,背后发生了什么?首先,JTA通过调用其内部API(特别是调用TransactionManager.suspend())暂时挂起当前与调用线程相关联的事务。(如果调用线程未关联任何事务(即使用事务属性NOT_SUPPORTED或没有事务上下文调用方法),则返回null对象引用),并获取Transaction对象。一旦上述REQUIRES_NEW方法完成,将通过TransactionManager.resume()方法将此Transaction对象传递给它以重新将事务上下文与调用线程关联。无论是在同一线程还是在另一个线程上取决于JTA实现,因为规范并没有明确要求它是这样还是那样。

回答您的问题-当在事务上下文中调用具有事务属性REQUIRES_NEW的方法时,JTA实现事务唯一的方式是挂起线程中的事务并稍后在同一线程或另一个线程上恢复它。何时恢复?请记住,REQUIRES_NEW属性基本上意味着注释方法始终必须处于自己的事务中,这反过来又意味着该方法应该独立于调用堆栈上方的方法进行提交或回滚。挂起的事务将在带有事务属性REQUIRES_NEW的被调用方法提交或回滚后恢复。

作为附注,您可能已经知道,Bean Managed Transaction无法暂停事务,您无法通过编程方式执行此操作。只有JTA可以使用其内部事务管理API执行此操作,并且您可以通过使用CMT和事务属性以声明方式实现此操作。还要注意,如果过度使用此属性,可能会导致过多的事务开销。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接