Java线程异步处理任务

业务场景,用户登录后给用户发送一封通知邮件,邮件消息的产生和发送用ActiveMQ来实现,预想的效果是用户登录成功后直接返回登录成功的信息,邮件的发送在后台程序中启动一个线程,采用异步的方式来调用邮件发送的方法
最开始采用如下代码实现:


/**

 * 单个线程的线程池

 */

private static ExecutorService executorService = Executors.newSingleThreadExecutor();



executorService.submit(new Runnable() {

            @Override

            public void run() {

                sendLoginMail(toMail, subject, content);

            }

        });


但是后面发现一个问题,就是在发送邮件的过程中出现了异常,上面的代码是没办法得知的,不会有异常信息抛出,不便于问题的定位,所以就改为了以下这种方式:

FutureTask futureTask = new FutureTask(new Callable() {

            @Override

            public String call() throws Exception {

                sendLoginMail(toMail, subject, content);

                return "ok";

            }

        });

        executorService.submit(futureTask);

        try {

            futureTask.get();

        } catch (InterruptedException e) {

            e.printStackTrace();

            logger.error("发送邮件异常...");

        } catch (ExecutionException e) {

            logger.error("发送邮件异常...");

            e.printStackTrace();

        }


任务提交后调用futureTask.get()方法获取执行的结果,这样做能实现如果发生邮件的过程中出现了异常,那么异常信息会打印出来,
但是,但是,但是在今天测试登录功能的时候提示服务调用超时,后面查找到原因是因为ActiveMQ挂掉了,导致登录后向ActiveMQ里面发送消息的时候一直等待,直到服务调用超时,抛出异常。
那么问题就来了,为什么我是用线程池做任务的异步提交的,还会等到邮件发送的代码执行完才会返回呢?
原因就是:futureTask.get()方法,它会等到任务执行完后才能获取到执行的结果,所以这相当于还是同步,如果把上面代码的futureTask.get()段注释掉,再运行则能达到异步的效果。
附:

/**

 * 由通知服务将邮件信息发送至消息队列

 *

 * @param toMail

 * @param subject

 * @param content

 */

private void sendLoginMail(String toMail, String subject, String content) {

    MailParam mailParam = new MailParam(toMail, subject, content);

    notifySendFacade.sendMailNotify(mailParam);

}



/**

 * 发送邮件通知

 *

 * @param mailParam

 */

@Override

public void sendMailNotify(final MailParam mailParam) {

    logger.info("开始发送邮件消息...");

    notifyJmsTemplate.send(new MessageCreator() {

        public Message createMessage(Session session) throws JMSException {

            return session.createTextMessage(NotifyUtil.formatMail(mailParam));

        }

    });

    logger.info("邮件发送结束...");

}

心得感悟:

1、代码中加入必要的日志信息对后续问题的定位分析真的很重要,特别是对于一些关键性的步骤,对于上面的问题,一开始我也一脸懵逼,直到看到日志中有输出”开始发送邮件消息“,但是却一直没有输出”邮件发送结束“,所以判断可能是ActiveMQ挂掉了,果不其然,对问题的定位能更加快速。
2、对异常的正确处理也很重要。

你可能感兴趣的:(Java线程异步处理任务)