gpt4 book ai didi

java - Spring beans 中处理线程安全的方法及其优缺点

转载 作者:行者123 更新时间:2023-11-30 02:55:05 25 4
gpt4 key购买 nike

我们在我的网络应用程序(Jetty)中使用邮件服务。服务对象是在运行时使用 spring bean 注入(inject)的。

现在,该服务不是线程安全的。我们该如何处理这个问题?在阅读这里的一些帖子时,我发现了以下选项。请让我们了解以下优点和缺点。

  1. 同步邮件服务内部的方法(在网络应用程序中会很好吗?)
  2. 每次都创建新对象 - 这也会很昂贵,因为初始化和释放需要时间
  3. 对象池
  4. ThreadLocal - 每个线程一个服务对象

Spring 配置:

   <bean id="mailService" class="com.....MailService">
<property name="mailSender" ref="mailSender" />
<property name="registrationEmailMessage" ref="registrationEmail" />
...
</bean>

Java Bean

@Autowired
MailService mailService;

最佳答案

  1. 同步邮件服务内的方法。
    通过阻塞进行同步会减慢应用程序的速度,具体取决于同步块(synchronized block)的执行时间。如果它是一个 singleton bean,则对 MailService 的调用将按顺序执行。即使它是一个 prototype bean,它仍然可以从不同的线程同时调用,并且会导致顺序执行。

  2. 每次都创建新对象。如果它不消耗大量时间和资源,那么它是一个很好的解决方案。在方法中创建新对象作为局部变量,它们不会在线程之间共享。

  3. ThreadLocal。强大的概念,但也有自己的问题:

    • 变量可以在任何地方访问,这违反了封装性。可能会导致诸如从 DAO 对象中的 ThreadLocals 获取 HttpServletRequest 之类的做法。
    • 容易引入内存泄漏。如果应用程序类之一在 ThreadLocal 变量中存储了一个值,并且在手头的任务完成后没有将其删除,则该对象的副本将保留在线程中(来自应用程序服务器线程池)。由于池化线程的生命周期超过了应用程序的生命周期,因此它将阻止该对象以及负责加载应用程序的类加载器被垃圾收集。我们已经创建了一个泄漏,它有机会以旧的 java.lang.OutOfMemoryError: PermGen space 形式出现。
      考虑到它可能造成的危害,我们应该尽可能避免使用 ThreadLocal。
  4. 对象池。我支持这个解决方案。在这种情况下,线程安全可以通过编写一个新的线程安全优化的 silgleton 包装 bean 来实现,在这种情况下,它将包含 MailService 对象池。可以从任何线程安全地访问包装器,并将执行重定向到池。 Here就是一个例子。

关于java - Spring beans 中处理线程安全的方法及其优缺点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37476408/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com