springboot-线程池简单使用
最近做项目,关于订单创建时候因为需要调用远程http服务获取数据,然后校验并写入数据库和修改数据库,
导致接口效率低,所以想到实现异步操作的方式解决。
在调用远程接口成功的时候即认为接口处理成功,返回给前段正确,并开启线程进行数据的写入和修改
1)添加配置类
1 package com.fieldsales.pos.config; 2 3 import lombok.Data; 4 import org.springframework.boot.context.properties.ConfigurationProperties; 5 import org.springframework.context.annotation.Bean; 6 import org.springframework.context.annotation.Configuration; 7 import org.springframework.scheduling.annotation.EnableAsync; 8 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 9 10 import java.util.concurrent.Executor; 11 import java.util.concurrent.ThreadPoolExecutor; 12 13 /** 14 * @author :CX 15 * @Date :Create in 2019/3/29 10:42 16 * @Effect :线程池配置类 17 */ 18 @Configuration 19 @EnableAsync 20 @ConfigurationProperties(prefix = "async") 21 @Data 22 public class ExecutorConfig { 23 24 private int corePoolSize; 25 private int maxPoolSize; 26 private int queueCapacity; 27 private String namePrefix; 28 29 30 @Bean(name = "asyncServiceExecutor") 31 public Executor asyncServiceExecutor() { 32 System.err.println("初始化线程池-----"); 33 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 34 //配置核心线程数 35 executor.setCorePoolSize(corePoolSize); 36 //配置最大线程数 37 executor.setMaxPoolSize(maxPoolSize); 38 //配置队列大小 39 executor.setQueueCapacity(queueCapacity); 40 //配置线程池中的线程的名称前缀 41 executor.setThreadNamePrefix(namePrefix); 42 43 // rejection-policy:当pool已经达到max size的时候,如何处理新任务 44 // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 45 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 46 //执行初始化 47 executor.initialize(); 48 return executor; 49 } 50 51 52 }
2)在配置文件中添加相应配置
1 #线程池配置 2 async: 3 # 配置核心线程数 4 corePoolSize: 30 5 # 配置最大线程数 6 maxPoolSize: 30 7 # 配置队列大小 8 queueCapacity: 9999 9 # 配置线程池中的线程的名称前缀 10 namePrefix: async-createOrderService-
3) 注入使用
1 //注入线程池 2 @Autowired 3 private Executor asyncServiceExecutor; 4 5 //上方代码接口调用成功 略 6 // 开启线程写入数据库数据 7 asyncServiceExecutor.execute(new Runnable() { 8 @Override 9 public void run() { 10 11 //标记数据是否正常写入 , 如果数据写入数据库异常,则每10S写出一次异常日志 12 boolean isAddOrder = false; 13 // 数据写入的时间 14 String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ").format(new Date()); 15 16 try{ 17 //开启事物写入数据 18 } catch (Throwable throwable) { 19 // 接口成功但是写入数据失败,则间隔抛出异常 20 while (true) { 21 logger.error("严重错误------------------------------------------------------------"); 22 logger.error("订单【" + resultdata.get("orderno").toString() + "】销售成功,但写入现场售票数据库失败!"); 23 logger.error("详情表: :" + JSON.toJSONString(orderInfos)); 24 logger.error("订单表:" + JSON.toJSONString(tkttransFormModel)); 25 logger.error("异常信息:" + throwable.getMessage()); 26 logger.error("错误时间:" + format); 27 try { 28 Thread.sleep(20000); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 } 35 }); 36 return HSResponse.ok(responsMap);