了解一下如何创建线程池
1、阿里巴巴不推荐Exceutors创建线程池
2、JDK的ThreadPoolExecutor
3、spring框架的ThreadPoolTaskExceutor
1.1Exceutors创建线程池的缺点
Exceutors创建会使用newFixedThreadPool等几种方式创建,在他的方法内部使用的任务队列是无界队列,如果出现处理速度慢,请求不断多的情况下,队列会一直增长,直至内存占满,会出现OOM。
ExecutorService executorService = Executors.newFixedThreadPool(40);
2.1ThreadPoolExecutor
/**
* int corePoolSize, 核心线程数量
* int maximumPoolSize, 最大线程数量
* long keepAliveTime, 存活时间
* TimeUnit unit, 单位
* BlockingQueue<Runnable> workQueue, 任务队列
* ThreadFactory threadFactory, 线程工厂
* RejectedExecutionHandler handler 拒绝策略
*
* 处理步骤:
* 1、线程数量小于corePoolSize,会新建线程,处理请求
* 2、线程数量等于corePoolSize,新请求会进入workQueue任务队列等待,等待空闲线程去读取并处理
* 3、workQueue任务队列已满,会新建线程入池,直到达到maximumPoolSize,这类线程又叫救急线程
* 4、已经超过maximumPoolSize之后,新的请求会被拒绝RejectedExecutionHandler
* 5、线程数量超过corePoolSize,空闲的线程会根据keepAliveTime自行销毁
*/
ThreadPoolExecutor executor = new ThreadPoolExecutor(1,
1,
0L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10),
null, null);
3.1ThreadPoolTaskExceutor的创建与使用
3.1.1新建配置类,使其加载到spring容器中去
添加@EnableAsync该注解,是启动多线程注解,之后@Async就会对标注的方法开启异步多线程调用
package com.base.owner.config;
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.ThreadPoolExecutor;
/**
* 配置线程池
* @date 2023年02月02日
*/
@Configuration
@EnableAsync
public class ThreadPoolConfig {
// 核心线程池大小
private int corePoolSize = 5;
// 最大可创建的线程数
private int maxPoolSize = 10;
// 队列最大长度
private int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间
private int keepAliveSeconds = 300;
private static final String threadNamePrefix = "ThreadPoolConfig-Service-"; // 线程池名前缀
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setThreadNamePrefix(threadNamePrefix);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
3.1.2如何创建线程池
@Async
public void testThreadPool() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Spring自带的线程池" + Thread.currentThread().getName() + "-" + sdf.format(new Date()));
System.out.println("111111111");
}
3.1.3 测试
@Test
public void testThreadPool() throws InterruptedException {
int i = 0 ;
while (i < 10){
classService.testThreadPool();
i ++ ;
Thread.sleep(1000);
}
}
测试结果如下,