17

我的容器 XML 配置:

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

并且myListener只是一个类

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

我已经concurrency="10"在我的 XML 中指定了。这究竟是什么意思?


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

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


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

  • 是否有许多线程创建了许多实例或使用了单个实例?
  • 我可以访问没有同步的实例字段吗?
  • SomeDependency dependency 实例化一次还是为每个线程/实例实例化?
  • 是否dependency需要线程安全?
4

1 回答 1

15

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.

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.

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

于 2014-04-28T13:52:09.693 回答