• @EventListener 监听事件 ,在同一个虚拟机中如何保证顺序执行


    前言

      如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
      而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


    @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());
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    编码监听事件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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    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));
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    编写要用线程池执行的方法:

        @Async("yzyThreadPoolExecutor")
        public void test(){
            ThreeEvent event1 = new ThreeEvent(NumUtil.getNum(EVENT_NUM));
            event1.setName("eiuyriuw");
            SpringContextUtil.getApplicationContext().publishEvent(event1);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    制作执行逻辑:

        @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++;
            }
    
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    2.4. 测试结果

    在这里插入图片描述
    可以看到在并发环境下,事件监听的执行顺序也可以得到保证。

  • 相关阅读:
    企业电子招投标采购系统源码之电子招投标的组成
    Anaconda Powershell Prompt和Anaconda Prompt的区别
    单点登录认识
    Semaphore学习
    面试必知的9个性能测试指标,你完全了解吗?
    大数据flink篇之一-基础知识
    MySQL 存储过程,语法+示例,超详细!!
    交易所金融知识
    java之流程控制
    【解决方案】Java 互联网项目中消息通知系统的设计与实现(上)
  • 原文地址:https://blog.csdn.net/weixin_38316697/article/details/132908339