views:

295

answers:

5

I have a method that will be used to send out email. i want to lock this method so only one thread can accses it per time and the rest pool up concurrently. should i synchronized the method or use spring @transactional PROPAGATION_REQUIRED ?

in my service layer

 //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();


}
+2  A: 

Why not make the method thread-safe by not using any instance level things?

However, I don't see how Spring's Transaction Management fits here. I mean Spring provides few transaction managers, i.e. DataSourceTransactionManager, JtaTransactionManager, HibernateTransactionManager all this is about database persistence. What you will configure for this email send out?

I believe, first you should show us why you worry about the thread-safety in the first place. Most probably you would like to show us some relevant code snippet or something. Then we might be able to suggest you something.

[Addendum]

When you are spawning a thread for every call to that method and not using anything from the state, then why you want to make the method synchronized. Making the method synchronized will not limit the number of threads in any way. There might be chance that before starting a new thread, previous thread might have finished the work, because of synchronization. The process of spawning a thread might go slower.

However, you should go with this until you find out that there are really many threads running and you are going out of memory. And if you really want to tackle that before time, then you should choose some blocking mechanism, something like Semaphore.

Adeel Ansari
my method is inside service layer. can you elaborate more ...how to do that
cometta
so spring transaction management is mainly for database stuff..
cometta
Yes, precisely. For you 'how' question, I think you need to show us the relevant code snippet, and tell us why are you worrying about thread-safety in this case. I mean what makes you think that your method should be synchronized or something.
Adeel Ansari
added the code.. please comment
cometta
+1  A: 

Hello,

I'm not sure if it answers your question, but instead of creating a new thread for every mail and calling start on it you could have an Executor or ExecutorService as a member of your class, as an implementation you could use a ThreadPoolExecutor with a pool size of 1. Your sendMail method would then submit Runnables to the executor.

pgras
+1  A: 

Spring @Transactional is not quite correct used in your case. The best bet is using synchorized method and add some thread pooling if your method called by hundreds time. But i guess you dont need thread pool here.

If you use thread to send blast email, then what's point synchronizing the method? if one process call your method and send email, other process will call you method even the first sending email process not yet finish.

If you intent to throttle the email sending process, you need to condider a queue (collection) and protect the collection with synchronize block. Create another process to monitor that queue, if there is one item in queue, pop it and send blast email, then wait until sending email process finish and check again the queue, if there is any item, continue to sending email process. If no item in the queue, make the monitor thread sleep for some chunk of time, then if sleep time is finish check the queue again.

Ifnu
+1  A: 

Another possibility would be to use JMS queues and put the email sending code in a Message Driven Bean (or through Spring JMS). You can then use your app server to control how many concurrent instances of your MDB will be used and throttle the outgoing emails that way.

beny23
+1  A: 

in Sping 3.0 you can use @Async annotation to do task execution, so your method will be executed later and the method is returned directly without waiting for email to be sent.

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

then in application context you specify and don't forget to add xmlns for task schema.

If you want to delay the execution for certain amount of time, you may use @Scheduled annotation to your method.

Further tutorial about @Async and @Scheduled can be found here :

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

Ifnu