首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在默认bean作用域为singleton的情况下,发生并发调用不是很糟糕吗?

在默认bean作用域为singleton的情况下,发生并发调用不是很糟糕吗?
EN

Stack Overflow用户
提问于 2011-09-29 20:24:22
回答 5查看 4.7K关注 0票数 8

我声明了一个Spring bean,它每隔几秒钟轮询我的电子邮件服务器。如果有邮件,它会获取它,并尝试提取其中的任何附件。然后将这些文件提交到Uploader,Uploader安全地存储这些文件。上传器也被声明为Spring bean。第三个bean将电子邮件的发送者与文件的文件名相关联,并将其存储在DB中。

事实证明,当几个人试图同时发送电子邮件时,发生了一堆混乱的事情。数据库中的记录文件名错误。有些根本没有得到文件名,等等。

我将这个问题归因于bean的默认作用域是单例的。这意味着一堆线程可能同时处理一个相同的实例。问题是如何解决这个问题。

如果我同步所有敏感的方法,那么所有的线程都会堆叠在一起并相互等待,这有点违背了多线程的整体思想。

另一方面,将bean的作用域限定为"request“将创建每个bean的新实例,如果我们谈到内存消耗和线程调度,这也不是很好。

我很困惑。我该怎么办?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-09-29 20:50:39

我同意@Bozho和@stivio的答案。

首选的选项是在单个作用域的bean中传递store no state,并将上下文对象传递给方法,或者使用为每个处理周期创建的原型/请求作用域的bean。通过选择这些方法中的一种,通常可以避免同步,并且您可以获得更高的性能,同时避免死锁。只需确保你没有修改任何共享状态,比如静态成员。

每种方法都有优缺点:

  1. Singlton beans充当一个类似服务类,有些人可能会说这不是一个好的面向对象的方法上下文,因为长方法链中的方法可能会使您的代码变得混乱,如果您不是这样的话,careful.
  2. Prototype beans可能会持有大量内存的时间比您预期的要长,并可能导致内存耗尽。您需要小心处理这些beans.
  3. Prototype beans的生命周期,这可能会使您的设计更简洁。但是,请确保您没有通过多个线程重用beans。

在大多数简单的情况下,我倾向于使用服务方法。您还可以让这些单例bean创建一个处理对象,该对象可以保存计算的状态。对于更复杂的场景,这是一种最适合您的解决方案。

编辑:有些情况下,您有一个依赖于prototype作用域bean的单例bean,并且您希望为每个方法调用都有一个新的prototype bean实例。Spring为此提供了几种解决方案:

第一种是使用Method Injection,如Spring参考文档中所述。我真的不喜欢这种方法,因为它迫使你的类变得抽象。

第二种方法是使用ServiceLocatorFactoryBean,或您自己的工厂类(需要注入依赖项并调用构造函数)。这种方法在大多数情况下都工作得很好,并且不会将您与Spring结合在一起。

在某些情况下,您还希望原型bean具有运行时依赖项。我的一个好朋友在这里写了一篇很好的文章:http://techo-ecco.com/blog/spring-prototype-scoped-beans-and-dependency-injection/

票数 8
EN

Stack Overflow用户

发布于 2011-09-29 20:30:07

单例作用域的bean不应该包含任何状态-这通常就解决了问题。如果您只将数据作为方法参数传递,而不将其分配给字段,那么您将是安全的。

票数 12
EN

Stack Overflow用户

发布于 2011-09-29 20:32:10

否则,只需将bean声明为request,不用担心内存消耗,垃圾回收会将其清除,只要有足够的内存,也不会有性能问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7597266

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档