實現異步有哪些方法 原

有哪些方法可以實現異步呢?

方式一: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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章