Java线程异步处理任务

作者: 会跳舞的机器人 | 来源:发表于2016-08-16 00:33 被阅读1390次

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

 * 单个线程的线程池

 */

private static ExecutorService executorService = Executors.newSingleThreadExecutor();

</code></pre>
<pre><code>
executorService.submit(new Runnable() {

            @Override

            public void run() {

                sendLoginMail(toMail, subject, content);

            }

        });

</code></pre>
但是后面发现一个问题,就是在发送邮件的过程中出现了异常,上面的代码是没办法得知的,不会有异常信息抛出,不便于问题的定位,所以就改为了以下这种方式:
<pre><code>
FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {

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

        }

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

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

 *

 * @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);

}

</code></pre>
<pre><code>
/**

 * 发送邮件通知

 *

 * @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("邮件发送结束...");

}

</code></pre>

心得感悟:

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

相关文章

  • Java线程异步处理任务

    业务场景,用户登录后给用户发送一封通知邮件,邮件消息的产生和发送用ActiveMQ来实现,预想的效果是用户登录成功...

  • 谈谈FutureTask的实现

    概述 ​ 在使用java多线程解决问题的时候,为了提高效率,我们常常会异步处理一些计算任务并在最后异步...

  • iOS开发多线程(GCD)

    相关概念 队列:用于储存任务 线程:处理任务的单元 sync:同步处理(立即处理) async:异步处理(稍后处理...

  • JavaScript执行机制

    概述 为什么javascript是单线程的?为什么需要存在异步任务?JavaScript怎么处理异步任务的?宏任务...

  • 多线程异步任务处理

    @(多线程&&并发) 多线程异步任务处理 欢迎关注作者简书csdn传送门   我们常用ThreadPoolExec...

  • 线程池工作原理

    什么是线程池 Java中,使用线程来异步执行任务。Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建...

  • Android 线程池

    在使用线程处理异步任务时,如果每次执行任务都去创建线程执行完成任务又销毁线程,由于创建线程和销毁线程会需要一些CP...

  • Android回顾--(八) 异步任务、Handler通信

    异步任务: 什么是异步任务?一切使用多线程完成的任务均可以称为异步任务-->使用线程来完成任务。 异步任务的优缺点...

  • Java多线程学习之Executor框架

    在Java中,使用线程来异步执行任务。Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来...

  • AsyncTask Code 分析

    AysncTask即异步任务,是Android给我们提供的一个处理异步任务的类.通过此类,可以实现UI线程和后台线...

网友评论

    本文标题:Java线程异步处理任务

    本文链接:https://www.haomeiwen.com/subject/lfqpsttx.html