文档章节

实现异步有哪些方法

黄威
 黄威
发布于 07/18 01:11
字数 783
阅读 39
收藏 0

有哪些方法可以实现异步呢?

方式一:java 线程池

示例:

@Test
    public final void test_ThreadPool() throws InterruptedException {
        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor=new ScheduledThreadPoolExecutor(2);

        scheduledThreadPoolExecutor.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("两秒之后执行 :" );
            }
        }, 2, TimeUnit.SECONDS);
        Thread.sleep(3000);
    }

方式二:使用消息队列

依赖

 <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit</artifactId>
            <version>1.7.6.RELEASE</version>
        </dependency>

调用场景:

if (null != increaseLevel && increaseLevel) {
                //只要考试通过,则升级经纪人级别,对应字段"level"
                this.agentDao.increasByOne(userId, "level");

                int msgType = 4;//参考RabbitMessageInfo 中type的含义
                Map map = new HashMap();
                map.put("userId", userId);
                //                map.put()
                rmqProducerService.sendRabbitMessage(msgType, map);
            }

消息推送的Service:

@Component
public class RmqProducerService {
    protected static Logger logger = Logger.getLogger(RmqProducerService.class);
        @Resource(name = "rmqProducer")
    private IRmqProducer producer;

    public void sendRabbitMessage(int msgType, Object map) {
        sendRabbitMessage(msgType, map, -1);
    }

    /***
     *
     * @param msgType
     * @param map
     * @param delaySecond : -1:不延迟;不传值默认为5,单位:秒
     */
    public void sendRabbitMessage(int msgType, Object map, Integer delaySecond) {
        try {
            producer = (IRmqProducer) SpringMVCUtil.getBean("rmqProducer");
            if (null == producer) {
                logger.info("没有设置推送 rmqProducer");
                return;
            }
            //通过消息队列,提示用户成功升级
            RabbitMessageInfo rabbitMessageInfo = new RabbitMessageInfo(msgType);

            rabbitMessageInfo.setValue(map);
            this.producer.sendMessage(rabbitMessageInfo.toJson(), delaySecond);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
    }
}

IRmqProducer的实现

@Component
public class RmqProducer implements IRmqProducer {
    protected static final Logger logger = Logger.getLogger(RmqProducer.class);
    private RabbitTemplate template;
    @Value("${rabbit.routingkey}")
    private String routingKey;
    @Value("${rabbit.DirectExchange}")
    private String exchange;

    public RmqProducer() {

    }
    @Autowired
    public RmqProducer(RabbitTemplate template) {
        this.template = template;
    }


    /***
     *
     * @param content
     * @param delaySecond : -1:不延迟;不传值默认为5,单位:秒
     */
    public void sendMessage(String content, Integer delaySecond) {
        if (exchange.equals(routingKey)) {
            logger.error("exchange 和routingKey相同,请确认配置是否有误");
        }
        MessageProperties properties = getDelayMessageProperties(delaySecond);

        try {
            MessageBuilder messageBuilder = MessageBuilder.withBody(content.getBytes(SystemHWUtil.CHARSET_UTF));
            if (null != properties) {
                messageBuilder.andProperties(properties);
            }
            template.send(exchange, routingKey,
                    messageBuilder.build());
//            template.convertAndSend(exchange, routingKey, content, correlationId);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
    }

    /***
     *
     * @param delaySecond :  -1:不延迟;不传值默认为5,单位:秒
     * @return
     */
    public static MessageProperties getDelayMessageProperties(Integer delaySecond) {
        MessageProperties properties = null;
        boolean delaySecondNull = (delaySecond == null);
        if (null == delaySecond) {
            delaySecond = 5;
        }
        if (delaySecondNull || ((!delaySecondNull) && -1 != delaySecond)) {
            properties = new MessageProperties();
            properties.setDelay(1000 * delaySecond);
        }
        return properties;
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String s) {
        System.out.println(" 回调id:" + correlationData + "ack:" + ack);
    }

消息的消费方

@Component("queueListenter")
public class QueueConsumerListenter extends QueueListenter {
    @Resource
    private EventBus eventBus;
    @Resource
    private SMSService smsService;
    @Override
    public void onMessageArrived(Message message, Channel channel) {
        byte[] body = message.getBody();
        if (ValueWidget.isNullOrEmpty(body)) {
            return;
        }
        String msgBody = new String(body); //{"type":"7","value":"{\"mobile\":\"18701670126\",\"smsCode\":\"ccc\"}"}
        RabbitMessageInfo rabbitMessageInfo = RabbitMessageUtil.extractRabbitMessageInfo(msgBody);
        System.out.println("receive time : " + TimeHWUtil.getCurrentFormattedTime());
        System.out.println("send time : " + rabbitMessageInfo.getCurr_time());
        System.out.println("receive msg : " + msgBody);
        System.out.println("receive type : " + rabbitMessageInfo.getType());
        /**
         * 自定义的类型:<br />
         * 1,注册完成;
         * 2:登录成功;<br />
         * 3:考试通过;
         * 4:升级成功;
         * 5,换绑手机号;
         * 7:发送短信
         */
        int type = Integer.parseInt(rabbitMessageInfo.getType());
        switch (type) {
            case 2://登录成功
                LoginSucessRabbitMessageInfo loginSucessRabbitMessageInfo = (LoginSucessRabbitMessageInfo) HWJacksonUtils.deSerialize(msgBody, LoginSucessRabbitMessageInfo.class);
                LoginSuccessLog loginSuccessLog = loginSucessRabbitMessageInfo.getValue();
                eventBus.post(loginSuccessLog);
                break;
            case 7:
                //发送短信
                SendSmsRabbitMessageDto sendSmsRabbitMessageInfoDto = null;
                SMSRabbitMessageValue smsRabbitMessageInfo = null;
                try {
                    sendSmsRabbitMessageInfoDto = (SendSmsRabbitMessageDto) HWJacksonUtils.deSerialize(msgBody, SendSmsRabbitMessageDto.class);
                } catch (Exception e) {
                    e.printStackTrace();
                    SendSmsRabbitMessageStrDto sendSmsRabbitMessageStrDto = (SendSmsRabbitMessageStrDto) HWJacksonUtils.deSerialize(msgBody, SendSmsRabbitMessageStrDto.class);
                    smsRabbitMessageInfo = (SMSRabbitMessageValue) HWJacksonUtils.deSerialize(sendSmsRabbitMessageStrDto.getValue(), SMSRabbitMessageValue.class);
                }

                if (null != sendSmsRabbitMessageInfoDto) {
                    smsRabbitMessageInfo = sendSmsRabbitMessageInfoDto.getValue();
                }

                if (null != smsRabbitMessageInfo) {
                    if (!ValueWidget.isNumeric(smsRabbitMessageInfo.getSmsCode())) {
                        LogicBusinessException.throwException("1001", "内容必须是数值");
                    }
                    smsService.sendSMSByCode(smsRabbitMessageInfo.getMobile(), smsRabbitMessageInfo.getSmsCode());
                }
        }
    }

}

方式三:使用定时器

使用注解: @Scheduled

依赖

<dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>

调用方式:

 @Scheduled(cron = "0 0 */4 * * ?")//每4小时执行一次
    public void updatePerOneHour() {
	}

 /***
     * 每天凌晨的1点半自动执行
     */
    @Scheduled(cron = "* 30 1 * * ?")
    public void updateUserOrderStatisticsAllCount() {
        //更新所有用户的UserOrderStatistics(未支付订单的总数, 待评价数量,申请退单/退款/售后的数量)
        this.customerService.updateAllUserOrderStatistics();

        //删除 houseInfo 不存在的购房订单
        this.purchaseHouseOrderDao.deleteDirtyData();
    }


方式四:guava 的 AsyncEventBus

参考:
https://google.github.io/guava/releases/17.0/api/docs/com/google/common/eventbus/AsyncEventBus.html

© 著作权归作者所有

共有 人打赏支持
黄威
粉丝 16
博文 65
码字总数 35996
作品 0
昌平
程序员
私信 提问
AsyncTask 的实现原理

在《Android异步处理二:使用AsyncTask异步更新UI界面》一文中,我们介绍了如何使用AsyncTask实现异步下载图片,并且更新图片到UI界面的方法。本篇我们将学习Framework层AsyncTask的实现原理...

鉴客
2011/09/17
7.7K
1
前端高频面试题 JavaScript篇

以下问题都来自于互联网前端面经分享,回答为笔者通过查阅资料加上自身理解总结,不保证解答的准确性,有兴趣讨论的同学可以留言或者私信讨论。 1.JS的异步机制? 2.闭包如何实现? 3.原型链、...

大雄的学习人生
06/25
0
0
在 Javascript 中用 Promise 进行异步编程

异步模式在web编程中变得越来越重要,对于web主流语言Javscript来说,这种模式实现起来不是很利索,为此,许多Javascript 库(比如 jQuery和Dojo)添加了一种称为promise的抽象(有时也称之为...

鉴客
2012/02/07
1K
0
一步一步实现一个Promise A+规范的 Promise

2015年6月,ES2015(即ES6)正式发布后受到了非常多的关注。其中很重要的一点是 Promise 被列为了正式规范。 在此之前很多库都对异步编程/回调地狱实现了类 Promise 的应对方案,比如 bluebi...

2015年6月,ES2015(即ES6)正式发布后受到了非常多的关注。其中很重要的一点是 Promise 被列为了正式规范。
05/15
0
0
iOS 面试全方位剖析 -- UI视图篇(二)

UITableView相关 事件传递&视图响应 图像显示原理 卡顿&掉帧 绘制原理&异步绘制 离屏渲染 面试问题总结 图像显示原理 具体的看一下CPU和GPU做了哪些事,看下图 } 此时的堆栈...

PetitBread
05/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

eureka多注册中心

eureka分区的深入讲解

miaojiangmin
22分钟前
1
0
RAM SSO功能重磅发布 —— 满足客户使用企业本地账号登录阿里云

阿里云RAM (Resource Access Management)为客户提供身份与访问控制管理服务。使用RAM,可以轻松创建并管理您的用户(比如雇员、企业开发的应用程序),并控制用户对云资源的访问权限。 对云资...

阿里云官方博客
25分钟前
0
0
Mysql 8.0 | #08004Client does not support authentication protocol requested by server

完整报错 #08004Client does not support authentication protocol requested by server; consider upgrading MySQL client 解决方法 Using the old mysql_native_password works:ALTER ......

云迹
27分钟前
0
0
kylin入门到实战

1.概述 kylin是一款开源的分布式数据分析工具,基于hadoop之上的sql查询接口,能支持超大规模的数据分析。响应时间在亚秒级别,其核心是预计算,计算结果存放在hbase中。 2.特性 可扩展超快O...

hblt-j
30分钟前
0
0
vagrant mac 安装和使用

varant 在mac上使用起来非常的方便,具体的下载步骤可以看这里https://segmentfault.com/a/1190000000264347 这里主要是记录一下配置文件 # -*- mode: ruby -*- # vi: set ft=ruby : # All V...

一千零一夜个为什么
30分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部