Java Spring AMQP Listener Container 中的并发是如何实现的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23341811/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:05:18  来源:igfitidea点击:

How is concurrency in Spring AMQP Listener Container implemented?

javaspringrabbitmqamqpspring-amqp

提问by Parobay

My container XML config:

我的容器 XML 配置:

<rabbit:listener-container
        connection-factory="myConnectionFactory"
        acknowledge="none"
        concurrency="10"
        requeue-rejected="false">
    <rabbit:listener ref="myListener" queues="myQueue"/>
</rabbit:listener-container>

and myListeneris just a class

并且myListener只是一个类

@Component("myListener")
public class MyListener implements MessageListener {
    @Autowired
    SomeDependency dependency;
    ....
}

I've specified concurrency="10"in my XML. What does this mean exactly?

我已经concurrency="10"在我的 XML 中指定了。这是什么意思完全相同



I've found some docs. They are not that helpful stating:

我找到了一些文档。他们不是那么有帮助,说明:

Specify the number of concurrent consumers to create. Default is 1.

指定要创建的并发消费者的数量。默认值为 1。



What I am interested in is whether MyListenerhas to be thread safe i.e.

我感兴趣的是是否MyListener必须是线程安全的,即

  • are there many instances created or single instance used by many threads?
  • can I access instance fields w/o synchronization?
  • is SomeDependency dependencyinstantiated once or for each thread/instance?
  • does dependencyneed to be thread safe?
  • 是否创建了多个实例或多个线程使用单个实例?
  • 我可以在没有同步的情况下访问实例字段吗?
  • SomeDependency dependency实例化一次还是为每个线程/实例实例化?
  • 是否dependency需要线程安全?

采纳答案by Gary Russell

Yes, to use concurrency, your listener has to be thread-safe. There is one listener instance per container. However, the <rabbit:listener-container/>namespace element is actually just a convenience for adding "shared" attributes, each listener element gets its own container.

是的,要使用并发,您的侦听器必须是线程安全的。每个容器有一个侦听器实例。但是,<rabbit:listener-container/>namespace 元素实际上只是为了方便添加“共享”属性,每个侦听器元素都有自己的容器。

It's generally best to use stateless objects (no fields that are written to), but that's not always possible.

通常最好使用无状态对象(没有写入的字段),但这并不总是可行的。

If your listener is not thread-safe, you can use...

如果您的侦听器不是线程安全的,您可以使用...

<rabbit:listener-container
    connection-factory="myConnectionFactory"
    acknowledge="none"
    requeue-rejected="false">
    <rabbit:listener ref="myListener" queues="myQueue"/>
    <rabbit:listener ref="myListener" queues="myQueue"/>
    <rabbit:listener ref="myListener" queues="myQueue"/>
    <rabbit:listener ref="myListener" queues="myQueue"/>
    ...
</rabbit:listener-container>

...and add @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE). You will then get a container for each listener and a different instance of the listener will be injected into each.

...并添加@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE). 然后,您将为每个侦听器获取一个容器,并且每个侦听器的不同实例将被注入。

You will also need prototype scope for any non-thread-safe dependencies injected into the listener.

对于注入侦听器的任何非线程安全依赖项,您还需要原型作用域。