文章目录
- 前言
- @EventListener 监听事件 ,在同一个虚拟机中如何保证顺序执行
- 1. 设计原理
- 2. 具体编码
- 2.1. 编码事件监听器
- 2.2. 制作一个生成序号方法
- 2.3. 制作测试代码
- 2.4. 测试结果
前言
如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!
@EventListener 监听事件 ,在同一个虚拟机中如何保证顺序执行
1. 设计原理
使用有序事件监听器:@EventListener注解可以接受一个org.springframework.core.Ordered接口来指示监听器的执行顺序。通过设置相应的顺序值,来控制事件监听器的执行顺序。
2. 具体编码
2.1. 编码事件监听器
编码事件监听器:
@Async
@EventListener(classes = ThreeEvent.class)
public void threeEventEventHandler(ThreeEvent event) {
log.info("=====================ThreeEvent===================:name:{},order:{}",event.getName(),event.getOrder());
}
编码监听事件VO并继承Ordered:
@Getter
@Setter
@ToString
public class ThreeEvent extends ApplicationEvent implements Ordered {
private int order;
private String name;
public ThreeEvent(int order) {
super("ThreeEvent async message");
this.order = order;
}
//======================================================
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int getOrder() {
return order;
}
}
2.2. 制作一个生成序号方法
此方法当天调用获得的值为9999999 至 0:
public class NumUtil {
public static Integer getNum(String type){
StringRedisTemplate template = (StringRedisTemplate) SpringContextUtil.getApplicationContext().getBean("stringRedisStdTemplate");
String today = DateUtils.format(new Date(), "yyyyMMdd");
String key = StringUtils.join(type,"_", today);
String numMax = "9999999";
if (template.hasKey(key)) {
Long decrement = template.opsForValue().decrement(key, 1L);
return decrement.intValue();
}
template.opsForValue().set(key,numMax);
template.expire(key, 24 * 60 * 60, TimeUnit.SECONDS);
return Integer.valueOf(numMax);
}
}
2.3. 制作测试代码
首先定义一个线程池:
@Configuration
@EnableAsync
public class ThreadPoolTaskExecutorConfig {
@Bean("yzyThreadPoolExecutor")
public ThreadPoolExecutor taskExecutor() {
int threads = Math.min(Runtime.getRuntime().availableProcessors() * 2, 20);
return new ThreadPoolExecutor(threads, threads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(100),
new NamedThreadFactory("jobThreadPoolExecutor-", false));
}
}
编写要用线程池执行的方法:
@Async("yzyThreadPoolExecutor")
public void test(){
ThreeEvent event1 = new ThreeEvent(NumUtil.getNum(EVENT_NUM));
event1.setName("eiuyriuw");
SpringContextUtil.getApplicationContext().publishEvent(event1);
}
制作执行逻辑:
@ApiOperation(value = "测试", notes = "测试")
@CommonLog(methodName = "测试",className = "TestController#event1")
@RequestMapping(value = "/v1/event1", method = RequestMethod.POST)
public void event1(){
for (int i = 0 ;i<100;i++) {
test();
i++;
}
}
2.4. 测试结果
可以看到在并发环境下,事件监听的执行顺序也可以得到保证。