一、异步处理
1.SpringBoot 工程中默认支持异步操作,但是我们需要首先在启动类的上面,添加启动异步操作的注解(@EnableAsync)描述
@EnableAsync
@SpringBootApplication
public class LogApplication {
public static void main(String[] args) {
SpringApplication.run(LogApplication.class, args);
}
}
2.定义切入点方法,假如此时某个业务方法需要执行异步操作,可以使用@Async 注解对方法进行描述,例如写日志的业务,这个方法执行时底层会在新的线程中进行调用
@Async
@Override
public void saveLog(SysLog sysLog) {
System.out.println("save.log.thread->"+Thread.currentThread().getName());
//模拟耗时操作
try{Thread.sleep(10000);}catch (Exception e){}
//try{TimeUnit.SECONDS.sleep(10);}catch (Exception e){} JDK1.8中的休眠玩法
sysLogDao.insertLog(sysLog);
}
3.自定义线程池的配置,当 springboot 中默认的线程池配置,不满足我们实际项目需求时,我们可以对线程池进行自定义的配置
#Spring Thread Pool
spring.task.execution.pool.core-size=9 一般为自己电脑cpu核的两倍加一
spring.task.execution.pool.max-size=256
spring.task.execution.pool.keep-alive=60000
spring.task.execution.pool.queue-capacity=128
spring.task.execution.thread-name-prefix=log-thread-
3.1)core-size:核心线程数,当池中线程数没达到core-size值时,每接收一个新的任务,都会创建一个新的线程,然后存储到池。若池中线程数已经达到core-size设置的值,再接收新的任务时,要检测是否有空闲的核心线程,假如有,则使用空闲的核心线程程序执行任务。
3.2)queue-capacity:队列内容假如核心线程数已达到 core-size 设置的值,并且所有的核心线程都在忙,再来新的任务,会将任务存储到任务队列。
3.3)max-size: 最大线程数,当任务队列已满,核心线程也都在忙,再来新的任务则会创建新的线程,但所有线程数不能超过 max-size 设置的值,否则可能会出现异常(拒绝执行。
3.4)keep-alive:线程空闲时间,假如池中的线程数多余 core-size 设置的值,此时又没有新的任务,则一旦空闲线程空闲时间超过 keep-alive 设置的时间值,则会被释放。
3.5)thread-name-prefix:线程名的前缀,项目中设置线程名的目的主要是为了对线程进行识别,一旦出现线程问题,可以更好的定位问题。
4.拒绝执行异常:RejectedExecutionException,处理能力达到并发上限(max-size)+(queue-capacity:)就会报错。
二、四种线程池拒绝策略
1.AbortPolicy:默认拒绝策略,ThreadPoolExecutor中直接抛出异常不处理。
2.CallerRunsPolicy:在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务。
3.DiscardPolicy:采用这个拒绝策略,会让被线程池拒绝的任务直接抛弃,不会抛异常也不会执行。
4.DiscardOldestPolicy:策略的作用是,当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。