创建用于发送电子邮件的后台线程 [英] Creating a background Thread for sending email

查看:79
本文介绍了创建用于发送电子邮件的后台线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在注册过程中发送电子邮件,因此,出于这个原因,我正在使用 Java Mail API ,它工作正常,但观察到 电子邮件过程需要将近 6秒(这太长了),因此Ajax调用使用户等待响应的时间太长了

I need to send a email during registration process , so for this reason i am using Java Mail API , this is working fine , but observed that the email process is taking nearly 6 seconds (which is too long ) so Ajax call making the user wait too long for response

因此,出于这个原因,我决定使用后台线程发送电子邮件,以便用户无需等待Ajax调用响应(Jersey REST Web服务调用)

so for this reason i have decided to use background thread for sending email so the user need not wait for the Ajax call response (Jersey REST Web Service call)

我的问题是,为每个请求在Web应用程序中创建线程是一种好习惯吗?

My question is it a good practice to creating threads in a webapplication for every request ??

@Path("/insertOrUpdateUser")
public class InsertOrUpdateUser {
        final static Logger logger = Logger.getLogger(InsertOrUpdateUser.class);
        @GET
        @Consumes("application/text")
        @Produces("application/json")
        public String getSalesUserData(@QueryParam(value = "empId") String empId
                        )
                        throws JSONException, SQLException {
                JSONObject final_jsonobject = new JSONObject();
            ExecutorService executorService = Executors.newFixedThreadPool(10);
                                executorService.execute(new Runnable() {
                                 public void run() {
                                         try {
                                                        SendEmailUtility.sendmail(emaildummy);
                                                } catch (IOException e) {
                                                        logger.error("failed",e);

                                                }
                                 }
                              });

                        }


                } catch (SQLException e) {

                } catch (Exception e) {


                }


                   finally {

                        }


                return response;
        }




}

这是我的实用程序类,用于发送电子邮件

And this is my Utility class for sending email

public class SendEmailUtility
{
    public static String sendmail(String sendto)
        throws IOException
    {
        String result = "fail";
        Properties props_load = getProperties();
        final String username = props_load.getProperty("username");
        final String password = props_load.getProperty("password");
        Properties props_send = new Properties();
        props_send.put("mail.smtp.auth", "true");
        props_send.put("mail.smtp.starttls.enable", "true");
        props_send.put("mail.smtp.host", props_load.getProperty("mail.smtp.host"));
        props_send.put("mail.smtp.port", props_load.getProperty("mail.smtp.port"));

        Session session = Session.getInstance(props_send,
            new javax.mail.Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication()
                {
                    return new PasswordAuthentication(username, password);
                }
            });

        try {
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(props_load.getProperty("setFrom")));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(sendto));
            message.setText("Some Text to be send in mail");
            Transport.send(message);
            result = "success";
        } catch (MessagingException e) {
            result = "fail";
            logger.error("Exception Occured - sendto: " + sendto, e);
        }
        return result;
    }
}

您能否让我知道这是否是在Web应用程序中执行的最佳做法?

Could you please let me know if this is best practice to do in a web application ??

推荐答案

您可以使用多种方法来处理它,因此,这完全取决于您的应用服务器是否具有那么多的资源(内存,线程等)来处理您的数据.实施,因此使您成为决定采用哪种方法的最佳人选.

There are host of ways you can handle it, so it all depends on whether your application server has that much resources (memory, threads etc.) to handle your implementation, so it makes you best person to decide on which approach to go.

因此,如果设计合理的话,生成并行线程来完成某件事并不是一个坏习惯,但是通常您应该使用受控线程.

As such it is not bad practice to spawn parallel threads for doing something if it is justified by design, but typically you should go with controlled threads.

请注意,无论使用newSingleThreadExecutor()还是newFixedThreadPool(nThreads),在幕后总是会创建一个ThreadPoolExecutor对象.

Please note that whether you use newSingleThreadExecutor() or newFixedThreadPool(nThreads), under-the-hoods there will always be a ThreadPoolExecutor object created.

我的建议是在列表中使用秒数选项,即受控线程数",并在其中指定最大线程数,如您所见.

My recommendation will be to use seconds option in below list i.e. "Controlled number of threads", and in that specify max thread count as you see fir.

在这种方法中,将为来自GUI的每个传入请求创建一个线程,因此,如果您收到10个插入/更新用户的请求,则将产生10个线程来发送电子邮件.

In this approach one thread will be created for each incoming request from GUI, so if you are getting 10 requests for inserting/updating user then 10 threads will be spawned which will send emails.

此方法的缺点是无法控制线程数,因此您可以以StackOverflowException结尾或可能是内存问题.

Downside of this approach is that there is no control on number of threads so you can end with StackOverflowException or may be memory issue.

请确保关闭您的执行器服务,否则将浪费JVM资源.

Please make sure to shutdown your executor service else you will end up wasting JVM resources.

// inside your getSalesUserData() method
ExecutorService emailExecutor = Executors.newSingleThreadExecutor();
        emailExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    SendEmailUtility.sendmail(emaildummy);
                } catch (IOException e) {
                    logger.error("failed", e);
                }
            }
        });
        emailExecutor.shutdown(); // it is very important to shutdown your non-singleton ExecutorService.

受控线程数

在这种方法中,将存在一些预定义的线程数,这些线程将处理您的电子邮件发送要求.在下面的示例中,我将启动一个最多包含10个线程的线程池,然后使用LinkedBlockingQueue实现,这样可以确保如果有10个以上的请求,并且当前所有10个线程都处于繁忙状态,那么将有过多的请求被使用.排队而不会丢失,这是通过Queue实现的Queue获得的优势.

Controlled number of threads

In this approach, some pre-defined number of threads will be present and those will process your email sending requirement. In below example I am starting a thread pool with max of 10 threads, then I am using a LinkedBlockingQueue implementation so this will ensure that if there are more than 10 requests and currently all my 10 threads are busy then excess of requests will be queued and not lost, this is the advantage you get with LinkedBlockingQueue implementation of Queue.

您可以在应用程序服务器启动时初始化单例ThreadPoolExecutor,如果没有请求,那么将不存在线程,因此这样做很安全.实际上,我在prod应用程序中使用了类似的配置.

You can initialize you singleton ThreadPoolExecutor upon application server start, if there are no requests then no threads will be present so it is safe to do so. In fact I use similar configuration for my prod application.

我使用的生存时间是1秒,所以如果一个线程在JVM中理想的时间超过1秒,那么它将死掉.

I am using time to live seconds as 1 seconds so if a thread is ideal in JVM for more than 1 seconds then it will die.

请注意,由于相同的线程池用于处理您的所有请求,因此应为单线程,并且不要关闭该线程池,否则您的任务将永远不会执行.

Please note that since same thread pool is used for processing all you requests, so it should be singleton and do not shutdown this thread pool else your tasks will never be executed.

// creating a thread pool with 10 threads, max alive time is 1 seconds, and linked blocking queue for unlimited queuing of requests.
        // if you want to process with 100 threads then replace both instances of 10 with 100, rest can remain same...
        // this should be a singleton
        ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

        // inside your getSalesUserData() method
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    SendEmailUtility.sendmail(emaildummy);
                } catch (IOException e) {
                    logger.error("failed", e);
                }
            }
        });

Java的默认缓存线程池

此方法与上面的方法非常相似,只是Java会为您将ThreadPoolExecutor初始化为ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());

此处最大线程数为Integer.MAX_VALUE,因此将根据需要创建线程,并且生存时间为60秒.

Here max number of threads will be Integer.MAX_VALUE, so threads will be created as needed and time to live will be 60 seconds.

如果您想使用这种方式,那么下面就是这种方式.

If you want to use this way then below is the way.

// this should be a singleton
        ExecutorService emailExecutor = Executors.newCachedThreadPool();

        // from you getSalesUserData() method
        emailExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    SendEmailUtility.sendmail(emaildummy);
                } catch (IOException e) {
                    logger.error("failed", e);
                }
            }
        });

这篇关于创建用于发送电子邮件的后台线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆