2019独角兽企业重金招聘Python工程师标准>>>
有哪些方法可以实现异步呢?
方式一: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);
}
方式二:使用消息队列
依赖
com.rabbitmq
amqp-client
4.2.0
org.springframework.amqp
spring-rabbit
1.7.6.RELEASE
调用场景:
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());
/**
* 自定义的类型:
* 1,注册完成;
* 2:登录成功;
* 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
依赖
org.quartz-scheduler
quartz
2.3.0
调用方式:
@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