spring 的 JavaMailSenderImpl 是线程安全的吗?

Is JavaMailSenderImpl of spring thread-safe?

我正在使用 spring 中的 JavaMailSenderImpl 在我的 Web 应用程序中发送电子邮件。我只创建了一个实例(实际上它被另一个使用 spring bean 创建的对象使用,并且是一个单例)。

那么问题来了,JavaMailSenderImpl 是线程安全的吗?在我的应用程序中,当多个线程同时使用 mailSender 时,会导致任何竞争条件吗?

不,不是。

虽然it has它的源代码中有一些同步,但用户、密码等字段没有同步访问权限。因此,如果您在一个线程中调用 setUsername,则无法保证其他线程的可见性。

是的,JavaMailSenderImpl 是线程安全的 一旦 它被构建。

看看执行实际工作的 doSend 方法。它只包含方法局部变量(因此每个调用 thread/stack 都有自己的实例)。 (这同样适用于添加一些功能的 send 方法)。

getSession 等方法是 synchronized,因此只有一个线程可以访问该方法。

使它成为线程安全的最重要的事情是(几乎)没有可变共享状态,并且存在的单个可变共享状态(Session)是synchronized

其次,它已经以单例方式在生产系统中使用它超过 12 年,并且从未遇到过任何并发问题。是的,我们在高度并发的应用程序中使用了它。 (这也是其他框架组件如 Spring Batch 和 Spring Integration 使用 JavaMailSender API 的方式)。

它是线程安全的,但值得补充的是它只能支持有限数量的并发调用。当我的第 4 个线程调用 sendMail 函数时出现以下错误:

org.springframework.mail.MailSendException:失败消息:com.sun.mail.smtp.SMTPSendFailedException:432 4.3.2 STOREDRV.ClientSubmit;超过发件人线程限制 [Hostname=***]。因此,您应该捕获运行时异常并将其记录下来,否则它只会被该线程的执行程序服务 运行 吞没。