spring的异步处理@Async注释的简单使用

2020-06-25  本文已影响0人  雨中的单车

用@Async注释bean的方法将使其在单独的线程中执行,即调用方将不等待被调用方法的完成。这里说的是方法不是类。
首先配置线程配置类
实现org.springframework.scheduling.annotation.AsyncConfigurer.AsyncConfigurer接口,重写getAsyncExecutor()和getAsyncUncaughtExceptionHandler()方法,第一个方法配置线程池,第二个方法处理异步方法发生异常时使用的实例,此处暂未实现。

@Configuration
@ComponentScan("com.jbtx.Thread")
@EnableAsync
// 线程配置类
public class SpringAsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(80);// 最小线程数
        taskExecutor.setMaxPoolSize(100);// 最大线程数
        taskExecutor.setQueueCapacity(25);// 等待队列
        //初始化
        taskExecutor.initialize();
        return taskExecutor;
    }
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler(){
        return null;
    }
}

@ComponentScan("com.jbtx.Thread")这个配置一定要注意不要和别的配置扫描重叠,最好指定到标注@Async注释bean就可以了,不然在springboot配置启动时会出现嵌套异常(nested exception).

执行异步处理的类,通过@Service注释定义一个bean。我这个程序的任务是要做海康摄像机设备状态检测,check()方法首先是抽取需要检测的设备信息,然后交给equipmentCheck()方法做具体的设备检测。原来是顺序检测,就是第一个设备处理完,才开始第二个设备检测,因为有故障的设备检测返回时间明显变长,这样我扫描一次80台左右的设备大约需要两分钟时间(其中主要是有故障的设备返回时间长导致),采用多线程异步处理方式,每次处理不需要等待返回结果,每一个请求交由一个线程独立处理,耗时基本就是一台设备检测的时间,大大缩短检测时间。

@Service
public class SpringAsyncService {
    //设备监测,一小时扫描一次
    public void check() {
        HIKMonitorService hikMonitorService= ResourceApplicationContext.getApplicationContext().getBean(HIKMonitorService.class);
        EquipmentInfoDto equipmentInfoDto;
        while (true) {
            try {
                //获取要监测海康设备列表
                List equipmentList = hikMonitorService.getEquipmentList();
                for (int i = 0; i < equipmentList.size(); i++) {
                    equipmentInfoDto = (EquipmentInfoDto) equipmentList.get(i);
                    equipmentCheck(equipmentInfoDto);
                    //equipmentCheck(equipmentInfoDto);
                }
                //暂停一小时再次执行
                Thread.sleep(3600000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    @Async
    public void equipmentCheck(EquipmentInfoDto equipmentInfoDto){
        HIKMonitorService hikMonitorService= ResourceApplicationContext.getApplicationContext().getBean(HIKMonitorService.class);
        hikMonitorService.equipmentCheck(equipmentInfoDto);
    }
}

其中ResourceApplicationContext类是为了在异步处理方法中获取spring已经预先加载的类。因为SpringAsyncService是单独扫描加载的类,所以他获取不到spring已经预先加载的类。
最后在springboot的启动类main方法中增加以下代码完成异步处理方法加载和运行

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringAsyncService.class);
        SpringAsyncService springAsyncService = context.getBean(SpringAsyncService.class);
        springAsyncService.check();
上一篇下一篇

猜你喜欢

热点阅读