1、遇到的场景

  • 提高一下插入表的性能优化,两张表,先插旧的表,紧接着插新的表,若是一万多条数据就有点慢了

2、使用步骤

  • 用Spring提供的对ThreadPoolExecutor封装的线程池ThreadPoolTaskExecutor,直接使用注解启用

配置


@Configuration
@EnableAsync
public class ExecutorConfig { private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class); @Value("${async.executor.thread.core_pool_size}")
private int corePoolSize;
@Value("${async.executor.thread.max_pool_size}")
private int maxPoolSize;
@Value("${async.executor.thread.queue_capacity}")
private int queueCapacity;
@Value("${async.executor.thread.name.prefix}")
private String namePrefix; @Bean(name = "asyncServiceExecutor")
public Executor asyncServiceExecutor() {
logger.info("start asyncServiceExecutor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 配置核心线程数
executor.setCorePoolSize(corePoolSize);
// 配置最大线程数
executor.setMaxPoolSize(maxPoolSize);
// 配置队列大小
executor.setQueueCapacity(queueCapacity);
// 配置线程池中的线程的名称前缀
executor.setThreadNamePrefix(namePrefix); // rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
  • @Value取值配置是在application.properties中的

# 异步线程配置
# 配置核心线程数
async.executor.thread.core_pool_size = 5
# 配置最大线程数
async.executor.thread.max_pool_size = 5
# 配置队列大小
async.executor.thread.queue_capacity = 99999
# 配置线程池中的线程的名称前缀
async.executor.thread.name.prefix = async-service-

Demo测试

  • Service接口

public interface AsyncService { /**
* 执行异步任务
* 可以根据需求,自己加参数拟定
*/
void executeAsync();
}
  • Service实现类

@Service
public class AsyncServiceImpl implements AsyncService { private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class); @Override
@Async("asyncServiceExecutor")
public void executeAsync() {
logger.info("start executeAsync"); System.out.println("异步线程要做的事情");
System.out.println("可以在这里执行批量插入等耗时的事情"); logger.info("end executeAsync");
}
}
  • 在Controller层注入刚刚的Service即可

@Autowired
private AsyncService asyncService; @GetMapping("/async")
public void async(){
asyncService.executeAsync();
}
  • 使用测试工具测试即可看到相应的打印结果

3、摸索一下

-** 弄清楚线程池当时的情况,有多少线程在执行,多少在队列中等待?**

  • 创建一个ThreadPoolTaskExecutor的子类,在每次提交线程的时候都将当前线程池的运行状况打印出来

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.concurrent.ListenableFuture; import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor; public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { private static final Logger logger = LoggerFactory.getLogger(VisiableThreadPoolTaskExecutor.class); private void showThreadPoolInfo(String prefix) {
ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor(); if (null == threadPoolExecutor) {
return;
} logger.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]",
this.getThreadNamePrefix(),
prefix,
threadPoolExecutor.getTaskCount(),
threadPoolExecutor.getCompletedTaskCount(),
threadPoolExecutor.getActiveCount(),
threadPoolExecutor.getQueue().size());
} @Override
public void execute(Runnable task) {
showThreadPoolInfo("1. do execute");
super.execute(task);
} @Override
public void execute(Runnable task, long startTimeout) {
showThreadPoolInfo("2. do execute");
super.execute(task, startTimeout);
} @Override
public Future<?> submit(Runnable task) {
showThreadPoolInfo("1. do submit");
return super.submit(task);
} @Override
public <T> Future<T> submit(Callable<T> task) {
showThreadPoolInfo("2. do submit");
return super.submit(task);
} @Override
public ListenableFuture<?> submitListenable(Runnable task) {
showThreadPoolInfo("1. do submitListenable");
return super.submitListenable(task);
} @Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
showThreadPoolInfo("2. do submitListenable");
return super.submitListenable(task);
}
}
  • 进过测试发现:showThreadPoolInfo方法中将任务总数、已完成数、活跃线程数,队列大小都打印出来了,然后Override了父类的execute、submit等方法,在里面调用showThreadPoolInfo方法,这样每次有任务被提交到线程池的时候,都会将当前线程池的基本情况打印到日志中

  • 现在修改ExecutorConfig.javaasyncServiceExecutor方法,将ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor()改为ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor()


@Bean(name = "asyncServiceExecutor")
public Executor asyncServiceExecutor() {
logger.info("start asyncServiceExecutor");
// 在这里进行修改
ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
// 配置核心线程数
executor.setCorePoolSize(corePoolSize);
// 配置最大线程数
executor.setMaxPoolSize(maxPoolSize);
// 配置队列大小
executor.setQueueCapacity(queueCapacity);
// 配置线程池中的线程的名称前缀
executor.setThreadNamePrefix(namePrefix); // rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
  • 经最后测试得到的结果:提交任务到线程池的时候,调用的是submit(Callable task)这个方法,当前已经提交了3个任务,完成了3个,当前有0个线程在处理任务,还剩0个任务在队列中等待

SpringBoot线程池的更多相关文章

  1. springboot 线程池

    我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本 ...

  2. springboot线程池的使用和扩展(转)

    springboot线程池的使用和扩展 我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行, ...

  3. springboot线程池的使用和扩展

    我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本 ...

  4. springboot线程池@Async的使用和扩展

    我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本 ...

  5. [开源项目]可观测、易使用的SpringBoot线程池

    在开发spring boot应用服务的时候,难免会使用到异步任务及线程池.spring boot的线程池是可以自定义的,所以我们经常会在项目里面看到类似于下面这样的代码 @Bean public Ex ...

  6. springboot线程池任务调度类 -- ThreadPoolTaskScheduler介绍

    springboot中有一个bean,ThreadPoolTaskScheduler,可以很方便的对重复执行的任务进行调度管理:相比于通过java自带的周期性任务线程池ScheduleThreadPo ...

  7. Springboot 线程池配置

    最近的项目里要手动维护线程池,然后看到一起开发的小伙伴直接用Java了,我坚信Springboot不可能没这功能,于是查了些资料,果然有,这里给一下. 首先我们都知道@Async标签能让方法异步执行, ...

  8. SpringBoot 线程池配置 实现AsyncConfigurer接口方法

      目的是:  通过实现AsyncConfigurer自定义线程池,包含异常处理  实现AsyncConfigurer接口对异常线程池更加细粒度的控制 *a) 创建线程自己的线程池  b) 对void ...

  9. SpringBoot线程池的创建、@Async配置步骤及注意事项

    最近在做订单模块,用户购买服务类产品之后,需要进行预约,预约成功之后分别给商家和用户发送提醒短信.考虑发短信耗时的情况所以我想用异步的方法去执行,于是就在网上看见了Spring的@Async了. 但是 ...

  10. 【Java分享客栈】SpringBoot线程池参数搜一堆资料还是不会配,我花一天测试换你此生明白。

    一.前言   首先说一句,如果比较忙顺路点进来的,可以先收藏,有时间或用到了再看也行:   我相信很多人会有一个困惑,这个困惑和我之前一样,就是线程池这个玩意儿,感觉很高大上,用起来很fashion, ...

随机推荐

  1. 面试题目:手写一个LRU算法实现

    一.常见的内存淘汰算法 FIFO  先进先出 在这种淘汰算法中,先进⼊缓存的会先被淘汰 命中率很低 LRU Least recently used,最近最少使⽤get 根据数据的历史访问记录来进⾏淘汰 ...

  2. Altium Designer 原理图的绘制前导

    元件库.封装库设计 部分元器件厂商或者经销商不提供元件库和封装库,只给了元器件尺寸图,所以需要自行设计元件库文件或是封装库文件 元件库设计: 新建  .SchLib 文件:File  ->  N ...

  3. 推荐一款强大的轻量级模块化WEB前端快速开发框架--UIkit

    前言 今天给大家分享一款强大的轻量级模块化WEB前端快速开发框架--UIkit 到目前(2016-06-20)为止,UIkit在github上的Forks已达到了1350个,而Stars更是达到了69 ...

  4. IE中input标签密码框与文本框宽度不一样问题

    前言 在项目登录界面中有账户和密码的输入框,在Chrome中显示是正常的(本人使用的是Chrome浏览器,平时不用IE).等部署到客户的服务器上,访问时发现一个问题,在IE浏览器中文本框与密码框的宽度 ...

  5. HTML5 Canvas学习之路(六)

    一个炫酷的计时器 在慕课网看到一个canvas的课,感觉很炫酷,就把它看完了,然后记下来.http://www.imooc.com/learn/133 第一步:绘制要显示的时间 拿小球来绘制具体的数字 ...

  6. AMS分析 -- 启动过程

    一. AMS简介 AmS可以说是Android上层系统最核心的模块之一,其主要完成管理应用进程的生命周期以及进程的Activity,Service,Broadcast和Provider等. 从系统运行 ...

  7. echarts中饼图的legend自定义icon图片(扇形为例)

    效果图: 代码: 问题:// icon: "pin", // 这个字段控制形状 类型包括 circle,rect ,roundRect,triangle,diamond,pin,a ...

  8. 虚拟机上 安装 CentoOS 7.5 1804 过程记录

    1.准备安装镜像 在开始安装CentOS之前,必须下载安装ISO映像.镜像可从CentOS网站https://www.centos.org/download/.提供以下基本类型的镜像: DVD ISO ...

  9. try、catch、finally、return的执行顺序

    1. 不管有没有异常,finally里面的语句都会执行 2. 当try和catch中有返回语句时,finally里面的语句还是会执行 3. 如果finally里面没有return语句,try和catc ...

  10. Java 实例 - 读取文件内容

    原文作者:菜鸟教程 原文链接:Java 实例 - 读取文件内容(建议前往原文以获得最佳体验) 按行读取文本文件 import java.io.*; public class Main { public ...