1.线程池配置
package com.ruoyi.framework.config;
import com.ruoyi.common.utils.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线程池配置
*
* @author ruoyi
**/
@Configuration
@EnableAsync
public class ThreadPoolConfig
{
// 核心线程池大小
private int corePoolSize = 50;
// 最大可创建的线程数
private int maxPoolSize = 200;
// 队列最大长度
private int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间
private int keepAliveSeconds = 300;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
2.实例1
需求:100w数据插入按照每次插入1000条为一个线程,开list.size个线程。并且必须等待方法执行完毕后返回给前端,并且需要返回新增的id。
/**
* 批量新增xxx
* @param rouTingPathNetworkList xxx集合
* @return xxxid集合
* @throws ExecutionException
* @throws InterruptedException
*/
@PostMapping("/rouPathNetWorkAddBatch")
public List<Long> rouPathNetWorkAddBatch(@RequestBody List<PrjRoutingpathNetwork> rouTingPathNetworkList) throws ExecutionException, InterruptedException {
//按1000条分割
List<List<PrjRoutingpathNetwork>> networkList = ListUtils.partition(rouTingPathNetworkList, 1000);
//获取线程池中的@bean
ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor");
//倒计数器,networkList.size是锁数量也是 线程数量
CountDownLatch latch = new CountDownLatch(networkList.size());
//返回值id集合
List<Long> resultIds = new ArrayList<>();
try{
for (List<PrjRoutingpathNetwork> n : networkList) {
//每次循环创建一个线程 new Runnable()
executor.execute(() -> {
//执行任务
List<Long> ids = prjRoutingpathNetworkService.insertPrjRoutingpathNetworks(n);
resultIds.addAll(ids);
//去掉一把锁
latch.countDown();
});
}
//校验锁数量是否为0,(还有没有)
latch.await();
}catch (Exception e){
return new ArrayList<>();
}
Collections.sort(resultIds);
return resultIds;
}
3.实例2
需求:在方法内开多线程,处理耗时的业务处理,并且要求线程阻塞等待 业务部分处理完成,再往下走
=========================================================
用于排查耗时部分
//获取当前时间 long t = System.nanoTime();
线程中的某个方法
//用当前时间减去某个方法执行时的时间,获取这一段的耗时
System.err.println("xxx部分耗时:" + ((System.nanoTime() - t) / 1_000_000_000) + "秒");
=========================================================
//获取线程池中的@bean
ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor");
//倒计数器,networkList.size是锁数量也是 线程数量
CountDownLatch latch = new CountDownLatch(netList.size());
for (PrjNet net : netList) {
//每次循环创建一个线程 new Runnable()
executor.execute(() -> {
//获取当前时间
long t = System.nanoTime();
try {
//执行业务处理
} catch (Exception e) {
e.printStackTrace();
} finally {
//去掉一把锁
latch.countDown();
}
//输出每个线程耗时 时长
System.err.println("线程:" + Thread.currentThread().getName() + ",共耗时:" + ((System.nanoTime() - t) / 1_000_000_000) + "秒");
});
}
//校验锁数量是否为0,(还有没有)
latch.await();