一.配置线程池参数

@EnableAsync
@Configuration
public class TaskExecutorConfig {
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(60);
        // 设置最大线程数
        executor.setMaxPoolSize(100);
        // 设置队列容量
        executor.setQueueCapacity(300);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(60);
        // 设置默认线程名称
        executor.setThreadNamePrefix("hiksion-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }
}

二.调用方法上添加@Async注解

@Async
    @Transactional
    public void storePic(File file, byte[] bytes, ResourceRecordDto resouceRecordDto) throws IOException {
        // 将数据插入数据库(唯一键索引)
        ResourceRecordVo vo = null;
        try {
            vo = resourceRecordService.insertRecord(resouceRecordDto);
        } catch (DuplicateKeyException e) {
            log.error("数据文件已经存在,文件名称:{}", resouceRecordDto.getFileName());
            throw e;
        }

        @Cleanup
        BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(file));
        stream.write(bytes);
        // 数据处理打包好
        ResourceRecordVo finalVo = vo;
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                if (finalVo != null) {
                    ResourceRecordMessage msg = new ResourceRecordMessage();
                    msg.setResourceCompositeRecordId(finalVo.getResourceCompositeRecordId());
                    highDeviceSender.send(msg);
                }
            }
        });
    }

三.注意同方法内调用失效问题

ApplicationContext.getBean(clazz)

由于注解的生效使用的是切面,所以同方法内调用时,要从容器中获取当前类,然后使用获取的当前类的对象调用同类中的有注解的方法才会生效..