我有一个类,它使用以下参数实现
JmsListenerContainerFactory
:
factory.setSessionTransacted(true);
factory.setConcurrency("1");
factory.setAutoStartup(true);
还有另一个
AtomikosConnectionFactoryBean
类型的类,具有以下参数:
atomikosfactory.setMaxPoolSize(2);
我还有两个队列,每个队列都由一个消费者处理:
@JmsListener(containerFactory = "jmsListenerContainerFactory", destination = "${queue-one}")
@Transactional
public <T> void handleOne(final Message<T> message)
{
final var payload = message.getPayload();
final var handler = getHandler(payload.getClass(););
handler.handleOne(payload);
}
@JmsListener(containerFactory = "jmsListenerContainerFactory", destination = "${queue-two}")
@Transactional
public <T> void handleTwo(final Message<T> message)
{
final var payload = message.getPayload();
final var handler = getHandler(payload.getClass(););
handler.handleTwo(payload);
}
不幸的是,两个处理程序都需要访问数据库中的相同条目。目前,这会导致意外行为,因为两者都试图同时访问它。我正在寻找一种方法来确保它们按顺序运行而不是同时运行。
我试图让我的
handleOne
和 handleTwo
方法调用标记为 @Synchronized
的相同方法,以确保它们不会同时运行。这是有效的,因为其中一个事务在尝试访问资源时会回滚,但那时某些操作已经执行,无法回滚。当线程在资源释放后尝试再次运行时,这会导致稍后出现错误。
最终的解决方案是我可以使用以下参数设置将
ThreadPoolTaskExecuter
的对象传递给 JmsListenerContainerFactory
:
executor.setCorePoolSize(1);
executor.setMaxPoolSize(1);
executor.setQueueCapacity(100);
executor.initialize();
这具有所需的行为。