1

I have the below code working fine up to 150 consecutive threads. Anything over that and the server is getting unresponsive. Please help me with suggestions on how to properly integrate the multi-threading. I was thinking about ThreadPoolExecutor and ArrayBlockingQueue but thought I ask if there is already library out there that I could use or other solution more suitable for this class:

@Transactional
public class EmailServiceImpl implements EmailService{

private static final Logger log = Logger
        .getLogger(MailNotificationServiceImpl.class);
private JavaMailSender mailSender;
private MessageSource messageSource;
private FreeMarkerConfigurer freemarkerConfig;

public void sendEmail(final String subject, final String recipient, final ModelMap mm, final String emailTemplate, final String from) {

   try {
        MimeMessagePreparator preparator = new MimeMessagePreparator() {
            public void prepare(MimeMessage mimeMessage) throws Exception {
                MimeMessageHelper message = new MimeMeaassageHelper(

                mimeMessage);
                message.setFrom(from);
                message.setTo(recipient);
                message.setSubject(subject);

                //freemarker integration
                Template textTemplate = freemarkerConfig.getConfiguration().getTemplate(emailTemplate); // "/WEB-INF/email/*.ftl"
                log.debug(emailTemplate);
                final StringWriter textWriter = new StringWriter();
                textTemplate.process(mm, textWriter);

                message.setText(textWriter.toString(), true);
            }
        };
       Thread thread = new SendMail(preparator);
       thread.start();

    } catch (Exception e) {
        log.error(e);
    }          
}


class SendMail extends Thread {
    MimeMessagePreparator preparator;

    SendMail(MimeMessagePreparator preparator) {
        this.preparator = preparator;
    }

    public void run() {
        log.debug("About to send email:");
        mailSender.send(preparator);
        log.debug("Email send.");
    }
}



public void sendEmail(final String subject, final String recipient, final ModelMap mm, final String emailTemplate, final boolean flag, final String from) {
    if(flag){
        sendEmail(subject, recipient, mm, emailTemplate, from);
    }
}

public void sendEmail(final String subject, final String recipient, final ModelMap mm, final String emailTemplate, final boolean flag) {
    if(flag){
        sendEmail(subject, recipient, mm, emailTemplate, "support@domain.com");
    }
}    

public void sendEmail(final String subject, final String recipient, final ModelMap mm, final String emailTemplate) {
        sendEmail(subject, recipient, mm, emailTemplate, "support@domain.com");
}    

public void setMailSender(JavaMailSender mailSender) {
    this.mailSender = mailSender;
}

private String gm(String messageName) {
    return messageSource.getMessage(messageName, null, null);
}

public void setMessageSource(MessageSource messageSource) {
    this.messageSource = messageSource;
}

public void setFreemarkerConfig(FreeMarkerConfigurer freemarkerConfig) {
    this.freemarkerConfig = freemarkerConfig;
}

}
MatBanik
  • 26,356
  • 39
  • 116
  • 178

1 Answers1

3

You should deffinately consider using an ExecutorService. There is only so much concurrency you can achieve with more threads until all processors are peaked and the operating systems spends more time switching thread context in and out.

If you limit the number of Threads running at any given time to even as little as 50 you should see good overall throughput.

You can try it like this:

ExecutorService executor = Executors.newFixedThreadPool(50);

public void sendEmail(final String subject, final String recipient, final ModelMap mm, final String emailTemplate, final String from) {
 MimeMessagePreparator preparator = new MimeMessagePreparator() {
       // rest of your mail building logic
      };

  executor.submit(preparator);

} 
John Vint
  • 39,695
  • 7
  • 78
  • 108