3

我有一种用于发送电子邮件的方法。我想锁定这个方法,这样每次只有一个线程可以访问它,其余的同时池化。我应该同步方法还是使用 spring @transactional PROPAGATION_REQUIRED ?

在我的服务层

 //each time use new thread to send out email
  public  void sendThroughSMTP(List<String> emails,String subject,String content){

            //each time will open and sent through port 25.  dont u think this will caused too many threads spawned?
            BlastEmailThread blastEmailThread = new BlastEmailThread(emails,subject,content);

            blastEmailThread.start();


}
4

6 回答 6

7

为什么不通过不使用任何实例级别的东西来使方法线程安全?

但是,我看不出 Spring 的事务管理如何适合这里。我的意思是 Spring 提供了很少的事务管理器,即DataSourceTransactionManager,所有这些都是关于数据库持久性的。您将为这封电子邮件发送什么配置?JtaTransactionManagerHibernateTransactionManager

我相信,首先你应该首先向我们展示你为什么担心线程安全。很可能您想向我们展示一些相关的代码片段或其他东西。那么我们也许可以给你一些建议。

[附录]

当您为对该方法的每次调用都生成一个线程并且不使用状态中的任何内容时,那么为什么要创建该方法synchronized。使方法同步不会以任何方式限制线程数。由于同步,在开始一个新线程之前,前一个线程可能已经完成了工作。产生线程的过程可能会变慢。

但是,您应该继续这样做,直到您发现确实有很多线程正在运行并且您的内存不足。如果你真的想提前解决这个问题,那么你应该选择一些阻塞机制,比如Semaphore

于 2009-12-23T03:58:48.620 回答
3

我不确定它是否回答了您的问题,但是您可以将ExecutorExecutorService作为类的成员,而不是为每封邮件创建一个新线程并在其上调用 start,作为实现,您可以使用ThreadPoolExecutor与池大小为 1。然后,您的 sendMail 方法会将 Runnables 提交给执行程序。

于 2009-12-23T07:41:26.503 回答
3

另一种可能性是使用 JMS 队列并将电子邮件发送代码放在消息驱动 Bean(或通过 Spring JMS)中。然后,您可以使用您的应用服务器来控制将使用多少个 MDB 并发实例,并以此方式限制外发电子邮件。

于 2009-12-23T08:16:33.560 回答
2

在Sping 3.0 中你可以使用@Async 注解来做任务执行,这样你的方法会在稍后执行,直接返回方法,不用等待邮件发送。

@Async
public  void sendThroughSMTP(List<String> emails,String subject,String content){
//Send emails here, you can directly send lots of email
}

然后在应用程序上下文中指定并且不要忘记为任务模式添加 xmlns。

如果你想延迟执行一定的时间,你可以在你的方法中使用@Scheduled 注解。

关于@Async 和@Scheduled 的更多教程可以在这里找到:

http://blog.springsource.com/2010/01/05/task-scheduling-simplifications-in-spring-3-0/

于 2010-10-20T13:28:41.123 回答
1

在您的情况下使用 Spring @Transactional 并不完全正确。如果您的方法被调用数百次,最好的办法是使用同步方法并添加一些线程池。但我想你在这里不需要线程池。

如果您使用线程发送爆炸电子邮件,那么同步方法有什么意义?如果一个进程调用您的方法并发送电子邮件,即使第一个发送电子邮件过程尚未完成,其他进程也会调用您的方法。

如果您打算限制电子邮件发送过程,则需要考虑一个队列(集合)并使用同步块保护集合。创建另一个进程来监控该队列,如果队列中有一个项目,则将其弹出并发送爆炸电子邮件,然后等待发送电子邮件过程完成并再次检查队列,如果有任何项目,则继续发送电子邮件过程。如果队列中没有项目,则让监控线程休眠一段时间,然后如果休眠时间结束,请再次检查队列。

于 2009-12-23T07:55:52.583 回答
1

使您的服务 asingleton并添加synchronized到您的方法中。

于 2014-07-16T21:48:45.787 回答