文章目录
- 线程工具类
- yml配置文件定义线程池参数
- 线程池配置类(供参考)
线程工具类
public class ThreadUtil {
private final static Logger logger = LoggerFactory.getLogger(ThreadUtil.class);
public static void sleepByWait(long timeout) throws InterruptedException {
byte[] lock = new byte[0];
synchronized (lock){
lock.wait(timeout);
}
lock = null;
}
public static RejectedExecutionHandler blockExecuteRejectHandle(String name){
return new BlockExecuteRejectHandle(name);
}
public static ThreadFactory threadFactory(String name){
return new TFactory(name);
}
static class TFactory implements ThreadFactory {
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public TFactory(String name) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = name.concat("-");
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
static class BlockExecuteRejectHandle implements RejectedExecutionHandler {
final String name;
public BlockExecuteRejectHandle(String name) {
this.name = name.concat("RejectHandle");
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
try {
logger.warn("{} 阻塞加入 | pool:{}",name,e);
e.getQueue().put(r);
} catch (Exception ex) {
logger.error("{} 阻塞加入异常",e,ex);
}
}
}
}
public static int avgCapacity(int dataSize, int maxTaskNum) {
int _c = dataSize / maxTaskNum;
if (_c == 0){
return 0;
}
return dataSize % maxTaskNum == 0 ? _c : _c + 1;
}
public static <T> void concurrentExecuteAndBlockResult(ThreadPoolExecutor executor, int maxTaskNum,Function<List<T>, Void> fun,List<T> ls){
if (ls.isEmpty()){
return;
}
int avgCapacity = ThreadUtil.avgCapacity(ls.size(), maxTaskNum);
if (avgCapacity <= 1){
fun.apply(ls);
}else {
List<List<T>> lists = Lists.partition(ls, avgCapacity);
CompletableFuture[] all = new CompletableFuture[lists.size()];
for (int i = 0; i < lists.size(); i++) {
List<T> tmp = lists.get(i);
if (tmp.isEmpty()){
continue;
}
all[i] = CompletableFuture.runAsync(() -> fun.apply(tmp), executor);
}
CompletableFuture.allOf(all).join();
}
}
public static <T> void concurrentExecuteAndBlockResultVo(ThreadPoolExecutor executor, int oneTaskDataSize,Function<List<T>, Void> fun,List<T> ls){
if (ls.isEmpty()){
return;
}
if (ls.size() <= oneTaskDataSize){
fun.apply(ls);
}else {
List<List<T>> lists = Lists.partition(ls, oneTaskDataSize);
CompletableFuture[] all = new CompletableFuture[lists.size()];
for (int i = 0; i < lists.size(); i++) {
List<T> tmp = lists.get(i);
if (tmp.isEmpty()){
continue;
}
all[i] = CompletableFuture.runAsync(() -> fun.apply(tmp), executor);
}
CompletableFuture.allOf(all).join();
}
}
public static <T> void concurrentExecuteAndBlockResultVoForAbortPolicyReject(ThreadPoolExecutor executor, int oneTaskDataSize, Function<List<T>, Void> fun, List<T> ls){
if (ls.isEmpty()){
return;
}
if (ls.size() <= oneTaskDataSize){
fun.apply(ls);
}else {
List<List<T>> lists = Lists.partition(ls, oneTaskDataSize);
CompletableFuture[] all = new CompletableFuture[lists.size()];
for (int i = 0; i < lists.size(); i++) {
List<T> tmp = lists.get(i);
if (tmp.isEmpty()){
continue;
}
int reNum = 0;
while (all[i] == null){
try {
all[i] = CompletableFuture.runAsync(() -> fun.apply(tmp), executor);
} catch (RejectedExecutionException e) {
if (reNum == 0){
logger.warn("线程池处理任务繁忙:{}",e.getMessage());
}
reNum++;
try {Thread.sleep(3);} catch (Exception e1) {}
}catch (Exception e){
logger.error("线程池处理任务异常",e);
break;
}
}
if (reNum>0){
logger.warn("线程池处理任务繁忙 重试次数:{}",reNum);
}
}
CompletableFuture.allOf(all).join();
}
}
public static <T> void concurrentExecuteAndBlockResult(ThreadPoolExecutor executor, int maxTaskNum,BiFunction<List<T>, Object, Void> fun, List<T> ls,Object p0){
if (ls.isEmpty()){
return;
}
int avgCapacity = ThreadUtil.avgCapacity(ls.size(), maxTaskNum);
if (avgCapacity <= 1){
fun.apply(ls,p0);
}else {
List<List<T>> lists = Lists.partition(ls, avgCapacity);
CompletableFuture[] all = new CompletableFuture[lists.size()];
for (int i = 0; i < lists.size(); i++) {
List<T> tmp = lists.get(i);
if (tmp.isEmpty()){
continue;
}
all[i] = CompletableFuture.runAsync(() -> fun.apply(tmp,p0), executor);
}
CompletableFuture.allOf(all).join();
}
}
public static <T> void concurrentExecuteAndBlockResult(ThreadPoolExecutor executor, int maxTaskNum,BiFunction<List<T>, Object[], Void> fun, List<T> ls,Object... oArr){
if (ls.isEmpty()){
return;
}
int avgCapacity = ThreadUtil.avgCapacity(ls.size(), maxTaskNum);
if (avgCapacity <= 1){
fun.apply(ls,oArr);
}else {
List<List<T>> lists = Lists.partition(ls, avgCapacity);
CompletableFuture[] all = new CompletableFuture[lists.size()];
for (int i = 0; i < lists.size(); i++) {
List<T> tmp = lists.get(i);
if (tmp.isEmpty()){
continue;
}
all[i] = CompletableFuture.runAsync(() -> fun.apply(tmp,oArr), executor);
}
CompletableFuture.allOf(all).join();
}
}
public static <T,R> List<R> exec(ThreadPoolExecutor executor, int maxTaskNum,
Function<List<T>, List<R>> fun,
List<T> dataLs){
if (dataLs.isEmpty()){
return new ArrayList<>();
}
int avgCapacity = avgCapacity(dataLs.size(), maxTaskNum);
if (avgCapacity <= 1){
return fun.apply(dataLs);
}else {
List<R> ret = new CopyOnWriteArrayList<>();
List<List<T>> lists = Lists.partition(dataLs, avgCapacity);
CompletableFuture<? extends List<? extends R>>[] all = new CompletableFuture[lists.size()];
for (int i = 0; i < lists.size(); i++) {
List<T> tmp = lists.get(i);
if (tmp.isEmpty()){
continue;
}
all[i] = CompletableFuture.supplyAsync(() -> fun.apply(tmp), executor).whenCompleteAsync((rv, ex) -> {
if (ex != null) {
ex.printStackTrace();
}
if (rv != null) {
ret.addAll(rv);
}
});
}
CompletableFuture.allOf(all).join();
return ret;
}
}
}
yml配置文件定义线程池参数
business-thread-pools:
sms:
collect-report-pool:
pool-core-size: 2
线程池配置类(供参考)
import com.xyc.sms.common.util.ThreadUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Configuration
public class BusinessThreadPoolConfig {
private final static Logger logger = LoggerFactory.getLogger(BusinessThreadPoolConfig.class);
@Bean(name = "collectReportPoolConfig")
@ConfigurationProperties(prefix = "business-thread-pools.sms.collect-report-pool")
public PoolConfig collectReportPoolConfig(){
return new PoolConfig("CollectReportPool");
}
@Bean(name = "queueConfig")
public PoolConfig queueTransferSqlConfig() {
return new PoolConfig("QueueTransferSql");
}
@Bean(name = "timToQueueThreadPool")
public ThreadPoolExecutor timToQueueThreadPool(@Qualifier("queueConfig") PoolConfig c) {
PoolConfig useConfig = c.printInitInfoAndReturnUse(true);
return new ThreadPoolExecutor(useConfig.getPoolCoreSize(), useConfig.getPoolMaxSize(), 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(),
ThreadUtil.threadFactory(useConfig.getPoolNamPrefix()),
new ThreadPoolExecutor.CallerRunsPolicy());
}
@Bean(name = "collectReportPool")
public ThreadPoolExecutor collectReportPool(@Qualifier("collectReportPoolConfig") PoolConfig c){
PoolConfig useConfig = c.printInitInfoAndReturnUse(true);
return new ThreadPoolExecutor(useConfig.getPoolCoreSize(),useConfig.getPoolMaxSize(),0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
ThreadUtil.threadFactory(useConfig.getPoolNamPrefix()),
ThreadUtil.blockExecuteRejectHandle(useConfig.getPoolNamPrefix()));
}
private class PoolConfig {
private int poolCoreSize = -1;
private int poolMaxSize = -1;
private int taskQueueMaxSize = -1;
private String poolNamPrefix;
private int poolCoreSize_default = 1;
private int poolMaxSize_default = 2;
private int taskQueueMaxSize_default = 1;
public PoolConfig(String poolNamPrefix) {
this.poolNamPrefix = poolNamPrefix;
}
public int getPoolCoreSize() {
return poolCoreSize;
}
public void setPoolCoreSize(int poolCoreSize) {
this.poolCoreSize = poolCoreSize;
}
public int getPoolMaxSize() {
return poolMaxSize;
}
public void setPoolMaxSize(int poolMaxSize) {
this.poolMaxSize = poolMaxSize;
}
public int getTaskQueueMaxSize() {
return taskQueueMaxSize;
}
public void setTaskQueueMaxSize(int taskQueueMaxSize) {
this.taskQueueMaxSize = taskQueueMaxSize;
}
public String getPoolNamPrefix() {
return poolNamPrefix;
}
public void setPoolNamPrefix(String poolNamPrefix) {
this.poolNamPrefix = poolNamPrefix;
}
public int getPoolCoreSize_default() {
return poolCoreSize_default;
}
public void setPoolCoreSize_default(int poolCoreSize_default) {
this.poolCoreSize_default = poolCoreSize_default;
}
public int getPoolMaxSize_default() {
return poolMaxSize_default;
}
public void setPoolMaxSize_default(int poolMaxSize_default) {
this.poolMaxSize_default = poolMaxSize_default;
}
public int getTaskQueueMaxSize_default() {
return taskQueueMaxSize_default;
}
public void setTaskQueueMaxSize_default(int taskQueueMaxSize_default) {
this.taskQueueMaxSize_default = taskQueueMaxSize_default;
}
private PoolConfig printInitInfoAndReturnUse(boolean isOnlyUseCore){
PoolConfig us = new PoolConfig(this.poolNamPrefix);
logger.info(String.format("****************************************%-5s初始化【%-25s】线程池配置项 开始%-5s****************************************","",us.getPoolNamPrefix(),""));
if (isOnlyUseCore){
us.setPoolCoreSize(this.poolCoreSize == -1?this.poolCoreSize_default:this.poolCoreSize);
us.setPoolMaxSize(us.getPoolCoreSize());
us.setTaskQueueMaxSize(Integer.MAX_VALUE);
logger.info(String.format("**************%-4s 加载 %-25s - %-20s 默认值: %-8d yml配置: %-8d 启动使用配置: %-5d**************",
"",us.getPoolNamPrefix(),"poolCoreSize", us.getPoolCoreSize_default(),this.poolCoreSize,us.getPoolCoreSize()));
logger.info(String.format("**************%-4s 加载 %-25s - %-20s 默认值: %-8d yml配置: %-8d 启动使用配置(使用core配置项): %-5d**************",
"",us.getPoolNamPrefix(),"poolMaxSize", us.getPoolMaxSize_default(), this.poolMaxSize,us.getPoolMaxSize()));
}else {
us.setPoolCoreSize(this.poolCoreSize == -1?this.poolCoreSize_default:this.poolCoreSize);
us.setPoolMaxSize(this.poolMaxSize == -1?this.poolMaxSize_default:this.poolMaxSize);
us.setTaskQueueMaxSize(this.taskQueueMaxSize == -1 ?this.taskQueueMaxSize_default : this.taskQueueMaxSize);
logger.info(String.format("**************%-4s 加载 %-25s - %-20s 默认值: %-8d yml配置: %-8d 启动使用配置: %-5d**************",
"",us.getPoolNamPrefix(),"poolCoreSize", us.getPoolCoreSize_default(),this.poolCoreSize,us.getPoolCoreSize()));
logger.info(String.format("**************%-4s 加载 %-25s - %-20s 默认值: %-8d yml配置: %-8d 启动使用配置: %-5d**************",
"",us.getPoolNamPrefix(),"poolMaxSize",us.getPoolMaxSize_default(), this.poolMaxSize,us.getPoolMaxSize()));
logger.info(String.format("**************%-4s 加载 %-25s - %-20s 默认值: %-8d yml配置: %-8d 启动使用配置: %-5d**************",
"",us.getPoolNamPrefix(),"taskQueueMaxSize", us.getTaskQueueMaxSize_default(), this.taskQueueMaxSize,us.getTaskQueueMaxSize()));
}
logger.info(String.format("****************************************%-5s初始化【%-25s】线程池配置项 结束%-5s****************************************","",us.getPoolNamPrefix(),""));
return us;
}
}
}