在阿里巴巴JAVA开发手册中有这样一个强制要求。
那么我们如何通过ThreadPoolExecutor来自定义线程池了?
位于java.util.concurrent.ThreadPoolExecutor类的构造器主要有如下几个参数
1.corePoolSize 核心线程数
2.maximumPoolSize 最大线程数
3.keepAliveTime 空闲线程保持激活时间
4.unit 空闲线程保持激活时间单元
5.workQueue 工作队列
6.rejectedExecutionHandler 任务拒绝处理器
然后来看下线程池的主要工作原理:
1.现在使用了线程池创建了一个任务,首先判断当前任务数是否大于核心线程数,如果未大于则新建线程
2.如果大于核心线程数,则判断当前任务队列是否已满,如果未满,则放入到任务队列进行等待
3.如果任务队列已满,并且队列不是无界队列,则判断是否超过了最大线程数,如果未超过,则创建临时线程
4.如果超过了最大线程数,则执行任务拒绝策略。
我们可以根据我们机器的配置以及实际的业务场景来设置这些参数。
这里我们新建一个ThreadPoolExecutorPool来自定义线程池
上代码:
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.util.StringUtils;
import java.util.Map;
import java.util.concurrent.*;
public class ThreadPoolExecutorUtil {
private static volatile ThreadPoolExecutorUtil INSTANCE;
private ThreadPoolExecutorUtil(){}
private static Map<String,ExecutorService> executorServiceMap = new ConcurrentHashMap<>();
public static ThreadPoolExecutorUtil getInstance() {
if (INSTANCE == null) {
synchronized (ThreadPoolExecutorUtil.class) {
if (INSTANCE == null) {
return new ThreadPoolExecutorUtil();
}
}
}
return INSTANCE;
}
/**
*
* @param corePoolSize 核心线程数
* @param maximumPoolSize 最大线程数
* @param keepAliveTime 线程保持激活时间
* @param unit 空闲线程等待单元
* @param workQueueSize 工作队列大小
* @param poolName 线程池名字
* @return 线程池
*/
public ExecutorService getThreadPoolExecutor(int corePoolSize,int maximumPoolSize,
long keepAliveTime,TimeUnit unit,
int workQueueSize,
String poolName) {
if (corePoolSize <= 0 || corePoolSize > maximumPoolSize ||
StringUtils.isEmpty(poolName) ||workQueueSize <= 0) {
throw new IllegalArgumentException("getThreadPoolExecutor argument illegal.");
}
if (executorServiceMap.containsKey(poolName)) {
return executorServiceMap.get(poolName);
}
return new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,
new LinkedBlockingQueue<>(workQueueSize),
new BasicThreadFactory.Builder().namingPattern(poolName).daemon(false).build(),
new ThreadPoolExecutor.AbortPolicy());
}
}
ps:这里我使用的是LinkedBlockingQueue队列,这个是无界队列,这里我们加入了一个线程池名字的参数,相同名字的线程池这里使用单例模式,将其放入到ConcurrentHashMap中,key为名字,value为线程池。
那怎么去使用了?
见如下demo:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolDemo {
private static ExecutorService executorService = ThreadPoolExecutorUtil.getInstance().getThreadPoolExecutor(4,20,
2000L,TimeUnit.SECONDS,200,"My Thread.");
public static void main(String[] args) {
MyThreadPoolDemo.invokeThreadPool();;
}
public static void invokeThreadPool() {
executorService.execute(()->{
System.out.println("当前线程: "+Thread.currentThread().getName());
for(int i = 0 ; i < 10 ; i++) {
System.out.println("当前值是: "+i);
}
});
executorService.shutdown();
}
}