线程安全

使用并发消息侦听器容器时,将在所有使用者线程上调用单个侦听器实例。 因此,侦听器需要是线程安全的,最好使用无状态侦听器。 如果无法使侦听器线程安全,或者添加同步会显著降低添加并发的好处,则可以使用以下几种技术之一:spring-doc.cn

  • 将容器与 prototype 范围的 bean 一起使用,以便每个容器都获得自己的实例(使用 时无法执行此操作)。nconcurrency=1MessageListener@KafkaListenerspring-doc.cn

  • 将状态保留在实例中。ThreadLocal<?>spring-doc.cn

  • 将单例侦听器委托给在 (或类似范围) 中声明的 bean。SimpleThreadScopespring-doc.cn

为了便于清理线程状态(对于前面列表中的第二项和第三项),从版本 2.2 开始,侦听器容器在每个线程退出时发布一个。 您可以通过 or 方法使用这些事件,以从范围中删除实例或线程范围的 bean。 请注意,它不会销毁具有销毁接口(例如 )的 bean,因此您应该自己创建实例。ConsumerStoppedEventApplicationListener@EventListenerThreadLocal<?>remove()SimpleThreadScopeDisposableBeandestroy()spring-doc.cn

默认情况下,应用程序上下文的事件 multicaster 在调用线程上调用事件侦听器。 如果将 multicaster 更改为使用异步执行程序,则线程清理无效。

关于虚拟线程和并发消息侦听器容器的特别说明

由于底层库类中的某些限制仍在使用块进行线程协调,因此应用程序在将虚拟线程与并发消息侦听器容器一起使用时需要谨慎。 启用虚拟线程后,如果并发性超过可用的平台线程数,则虚拟线程很可能被固定在平台线程上,并可能出现争用条件。 因此,随着 Spring for Apache Kafka 使用的第三方库发展为完全支持虚拟线程,建议将消息侦听器容器上的并发性保持等于或小于平台线程数。 这样,应用程序就可以避免线程与固定在平台线程上的虚拟线程之间的任何争用条件。synchronizedspring-doc.cn