SpringBoot中多线程批处理并获取处理结果的应用
在日常开发中有时候会遇到诸如:对文件进行批量处理并获取文件处理结果的需求;在这时我们一般会对该批次文件进行逐张处理,不得不说这是最简单的实现方式,在文件数量不大的情况下使用这中方式处理没有任何问题,但是当文件数量达到几百张时,非常浪费时间;这时我们使用多线程的方式,将这些文件交给更多的线程去处理并在该线程处理完成后获取最终处理结果,这样即可节约大量的文件等待处理时间,从而实现在最短的时间内将大批文件处理完成;甚至在硬件资源条件足够强大时能够瞬间处理完成,下面我们就简单描述一下在SpringBoot框架中使用多线程进行批处理的一种实现方式;
思维发散一下,其实就是对同时处理大量相同的任务。
-
第一步先进行springboot线程池的配置
这里的线程池各参数配置依据实际情况进行配置
@Configuration @EnableAsync public class AsyncConfig { @Bean("pInvoiceAsyncExecutor") public Executor pInvoiceAsyncExecutor() { log.info("start pInvoiceAsyncExecutor"); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //配置核心线程数 executor.setCorePoolSize(10); //配置队列大小 executor.setQueueCapacity(50); //配置最大线程数 executor.setMaxPoolSize(15); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix("pInvoice-AsyncExecutor-"); // rejection-policy:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); return executor; } }
-
编写异步执行的业务逻辑相关方法
注意此方法不能与调用者在同一类中,在同一类中会造成无法异步执行问题;
@Service public class PInvoiceProcess { @Async(value = "pInvoiceAsyncExecutor") public Future<PInvoiceAnalysis> pInvoiceAnalysis(User user, String busNo, byte[] bytes, String fileName){ //1.这里执行业务逻辑操作 //2.返回值根据业务需求可自定义类 return new AsyncResult(new PInvoiceAnalysis(result,message)); } }
-
最后就是调用此异步方法并等待获取执行结果了
@Autowired private PInvoiceProcess pInvoiceProcess; public RInvoiceSaveResult savePInvoice(){ //1.异步执行的结果 Map<String, Future<PInvoiceAnalysis>> futureMap = new HashMap<>(); for(a:as){ //2.异步执行并将异步结果暂存入map中 Future<PInvoiceAnalysis> pInvoiceAnalysisFuture = pInvoiceProcess.pInvoiceAnalysis(user, busNo, bytes, fileName); futureMap.put(fileName,pInvoiceAnalysisFuture); } //3.循环等待异步任务执行结果 while (futureMap.size()>0) { //遍历,判断线程是否执行完成 Set<String> keySet = futureMap.keySet(); List<String> keyList = new ArrayList(); keyList.addAll(keySet); for(String key : keyList){ Future<PInvoiceAnalysis> pInvoiceAnalysisFuture = futureMap.get(key); //4.执行完成,获取执行结果 if (pInvoiceAnalysisFuture.isDone()) { PInvoiceAnalysis pInvoiceAnalysis; try { pInvoiceAnalysis = pInvoiceAnalysisFuture.get(); } catch (InterruptedException e) { log.info("获取异步执行结果异常:", e); } //5.处理最终执行结果 doSomthing(pInvoiceAnalysis); //6.移除执行完成的线程结果 futureMap.remove(key); log.info("移除的key:{}",key); } } } }
-
这里只是一种伪代码的实现,具体的业务逻辑需要根据实际情况进行补充。