线程池 - 自定义线程池实现
用线程池来管理线程,减少系统消耗,线程数可控。
目录
一、自定义线程池代码
自定义使用 ThreadPoolTaskExecutor
package com.yuantiaokj.commonmodule.threadpool;
import org.springframework.beans.factory.annotation.Autowired;
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.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* ***********************************************************
* Copyright © 2019 Inc.All rights reserved. * *
* **********************************************************
*
* @program: pay_inspector
* @name: TaskExecutePool
* @author: Mr.Cnzz
* @create: 2019-11-28 15:25
* @description: 创建线程池
**/
@Configuration
@EnableAsync
public class TaskExecutePool {
/**
* 1.这种形式的线程池配置是需要在使用的方法上面@Async("taskExecutor"),
* 2.如果在使用的方法上面不加该注解那么spring就会使用默认的线程池
* 3.所以如果加@Async注解但是不指定使用的线程池,又想自己定义线程池那么就可以重写spring默认的线程池
* 4.所以第二个方法就是重写默认线程池
* 注意:完全可以把线程池的参数写到配置文件中
*/
@Autowired
private TaskThreadPoolConfig config;
@Bean("taskExecutePoolCnzz")
public Executor taskExecutePoolCnzz() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程池大小
executor.setCorePoolSize(config.getCorePoolSize());
//最大线程数
executor.setMaxPoolSize(config.getMaxPoolSize());
//队列容量
executor.setQueueCapacity(config.getQueueCapacity());
//活跃时间
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
//线程名字前缀
executor.setThreadNamePrefix("taskExecutePoolCnzz");
// setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}
}
配置类
package com.yuantiaokj.commonmodule.threadpool;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* ***********************************************************
* Copyright © 2019 Inc.All rights reserved. * *
* **********************************************************
*
* @program: pay_inspector
* @name: TaskThreadPoolConfig
* @author: Mr.Cnzz
* @create: 2019-11-28 15:21
* @description: 线程池配置类
**/
@ConfigurationProperties(prefix = "task.pool")
@Data
@Component
public class TaskThreadPoolConfig {
//核心线程
private int corePoolSize;
//最大线程
private int maxPoolSize;
//空闲时间
private int keepAliveSeconds;
//队列容量
private int queueCapacity;
}
yml 配置线程池参数
#线程池配置参数
task:
pool:
corePoolSize: 20 #设置核心线程数
maxPoolSize: 100 #设置最大线程数
keepAliveSeconds: 60 #设置线程活跃时间(秒)
queueCapacity: 50 #设置队列容量
启动类Application 添加异步注解
//开启线程异步支持
@EnableAsync
// 开启配置属性支持
@EnableConfigurationProperties({TaskThreadPoolConfig.class})
使用,springboot直接使用@Async异步执行
二、测试
@Async
public void printNum(String str) {
log.info("str={}", str);
}
@Resource
AsyncTest asyncTest;
@Test
public void testAsync(){
for (int i = 0; i <20 ; i++) {
asyncTest.printNum(String.valueOf(i));
}
}
这里注意调用方法要在不同的类才会生效,由于容器加载原因,在同一个类时需要容器重新加载下。
1、队列,最大线程数 都较小的情况下,会生成到10个线程,触发饱和策略,也会有主线程执行。
测试配置,实际按环境情况配置,这里为了看到测试效果
#线程池配置参数
task:
pool:
corePoolSize: 2 #设置核心线程数
maxPoolSize: 10 #设置最大线程数
keepAliveSeconds: 10 #设置线程活跃时间(秒)
queueCapacity: 5 #设置队列容量
2、增大队列容量,让在队列等待,只有2个主线程在跑
#线程池配置参数
task:
pool:
corePoolSize: 2 #设置核心线程数
maxPoolSize: 10 #设置最大线程数
keepAliveSeconds: 10 #设置线程活跃时间(秒)
queueCapacity: 20 #设置队列容量
3、稍微减少队列,看下当队列满了,及未达到线程总数,未饱和的情况
#线程池配置参数
task:
pool:
corePoolSize: 2 #设置核心线程数
maxPoolSize: 20 #设置最大线程数
keepAliveSeconds: 10 #设置线程活跃时间(秒)
queueCapacity: 15 #设置队列容量
具体参数配置及原理可参考 线程池-线程池参数及配置 https://blog.csdn.net/xinpz/article/details/110132365