线程统一管理
按照业务,建立多个线程池,每个线程池的线程独立。这样避免了多个业务之间的影响。如果多个业务共用一个线程池,会因为一个业务阻塞导致整个服务雪崩。
默认线程池,为边缘业务提供统一线程管理。不需要每个业务都建立独立的线程池,一些边缘的小型业务可以使用系统默认的线程池。
整体线程状态查询。可以查询整个系统的线程状态,分析哪些业务产生了阻塞。
自定义线程工厂
每个线程池都需要配一个threadFactory.
有两个地方需要注意:一个是线程的名字必须有明确的区分,一个是AtomicInteger的超界处理。
public class ThreadPoolThreadFactory implements ThreadFactory {
private AtomicInteger atomicInteger = new AtomicInteger();
private String threadName;
public ThreadPoolThreadFactory() {
this(ThreadPoolThreadFactory.class.getSimpleName());
}
public ThreadPoolThreadFactory(String threadName) {
this.threadName = threadName;
}
@Override
public Thread newThread(Runnable r) {
int number = atomicInteger.getAndUpdate(p -> (p + 1) % Integer.MAX_VALUE);
return new Thread(r, threadName + number);
}
}
自定义线程池工厂
- 提供默认线程池,不需要指定线程池名称。
- 可以自定义线程池,以及线程池的名称。
- 如果指定的线程池名称不存在,就会按照默认配置创建一个新的线程池。
- 线程池用ThreadPoolExecutor,而不是Executors的便利接口。
- 提供所有线程池的统计接口。
/**
* @author yunzhong
*
*/
public class ThreadPoolFactory {
public static final String DEFAULT_POOL = "DEFAULT_POOL";
private static final Map<String, ThreadPoolExecutor> poolMap = new ConcurrentHashMap<>();
private static ThreadPoolConfig threadPoolConfig = null;
public static ThreadPoolExecutor getPool() {
return getPool(DEFAULT_POOL);
}
/**
* @param poolName
* @return
*/
public static ThreadPoolExecutor getPool(String poolName) {
if (poolMap.containsKey(poolName)) {
return poolMap.get(poolName);
} else {
synchronized (poolMap) {
if (!poolMap.containsKey(poolName)) {
if (threadPoolConfig == null) {
threadPoolConfig = SpringUtil.getBean(ThreadPoolConfig.class);
}
poolMap.put(poolName,
new ThreadPoolExecutor(threadPoolConfig.getCorePoolSize(),
threadPoolConfig.getMaximumPoolSize(), threadPoolConfig.getKeepAliveTime(),
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(threadPoolConfig.getQueueSize()),
new ThreadPoolThreadFactory(DEFAULT_POOL), new ThreadPoolExecutor.AbortPolicy()));
}
}
return poolMap.get(poolName);
}
}
/**
* @param poolName
* @param corePoolSize
* @param maximumPoolSize
* @param keepAliveTime
* @param queueSize
* @param handler
* @return
*/
public static ThreadPoolExecutor getPool(String poolName, int corePoolSize, int maximumPoolSize, int keepAliveTime,
int queueSize, RejectedExecutionHandler handler) {
if (poolMap.containsKey(poolName)) {
return poolMap.get(poolName);
} else {
synchronized (poolMap) {
if (!poolMap.containsKey(poolName)) {
if (threadPoolConfig == null) {
threadPoolConfig = SpringUtil.getBean(ThreadPoolConfig.class);
}
poolMap.put(poolName,
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(queueSize), new ThreadPoolThreadFactory(DEFAULT_POOL),
handler));
}
}
return poolMap.get(poolName);
}
}
/**
* @return
*/
public static ThreadPoolsInfo getInfo() {
ThreadPoolsInfo info = new ThreadPoolsInfo();
Iterator<Entry<String, ThreadPoolExecutor>> iterator = poolMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, ThreadPoolExecutor> next = iterator.next();
String key = next.getKey();
ThreadPoolExecutor value = next.getValue();
ThreadPoolInfo poolInfo = new ThreadPoolInfo(value);
info.getInfos().put(key, poolInfo);
info.appendActiveCount(poolInfo.getActiveCount());
info.appendWaitingSize(poolInfo.getWaitingSize());
}
return info;
}
public static void shutdown(String poolName) {
if (StringUtils.isEmpty(poolName)) {
return;
}
ThreadPoolExecutor threadPoolExecutor = poolMap.get(poolName);
if (threadPoolExecutor == null) {
return;
}
synchronized (poolMap) {
if (poolMap.containsKey(poolName)) {
poolMap.remove(poolName);
if (!threadPoolExecutor.isShutdown()) {
threadPoolExecutor.shutdownNow();
}
boolean isShutdown = false;
try {
isShutdown = threadPoolExecutor.awaitTermination(1000L, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!isShutdown) {
System.out.println("Invoke thread pool shutdown ,but raised exception .");
}
}
}
}
}
线程池核心概念:
/**
*
* <pre>
* corePoolSize : 核心线程数线程数定义了最小可以同时运行的线程数量。
* maximumPoolSize :当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
* keepAliveTime,unit: 存活时间
* workQueue:当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。
* handler: workQueue饱和策略.
* </pre>
*
* <pre>
* 饱和策略(如果线程数量达到最大线程数量并且队列也已经被放满):
* ThreadPoolExecutor.AbortPolicy:抛出 RejectedExecutionException来拒绝新任务的处理。
* ThreadPoolExecutor.CallerRunsPolicy:调用当前线程运行任务。如果当前程序已关闭,则会丢弃该任务。
* ThreadPoolExecutor.DiscardPolicy: 不处理新任务,直接丢弃掉。
* ThreadPoolExecutor.DiscardOldestPolicy: 丢弃最早的未处理的任务请求。
* </pre>
*/
线程池信息模型:
public class ThreadPoolsInfo {
/**
* @author yunzhong
*
*/
public static class ThreadPoolInfo {
private int corePoolSize;
private int maximumPoolSize;
private int activeCount;
private int remainingCapacity;
private int waitingSize;
public ThreadPoolInfo(ThreadPoolExecutor threadPoolExecutor) {
corePoolSize = threadPoolExecutor.getCorePoolSize();
maximumPoolSize = threadPoolExecutor.getMaximumPoolSize();
activeCount = threadPoolExecutor.getActiveCount();
remainingCapacity = threadPoolExecutor.getQueue().remainingCapacity();
waitingSize = threadPoolExecutor.getQueue().size();
}
public int getCorePoolSize() {
return corePoolSize;
}
public void setCorePoolSize(int corePoolSize) {
this.corePoolSize = corePoolSize;
}
public int getMaximumPoolSize() {
return maximumPoolSize;
}
public void setMaximumPoolSize(int maximumPoolSize) {
this.maximumPoolSize = maximumPoolSize;
}
public int getActiveCount() {
return activeCount;
}
public void setActiveCount(int activeCount) {
this.activeCount = activeCount;
}
public int getRemainingCapacity() {
return remainingCapacity;
}
public void setRemainingCapacity(int remainingCapacity) {
this.remainingCapacity = remainingCapacity;
}
public int getWaitingSize() {
return waitingSize;
}
public void setWaitingSize(int waitingSize) {
this.waitingSize = waitingSize;
}
}
private int totalActiveCount;
private int totalWaitingSize;
private Map<String, ThreadPoolInfo> infos = new HashMap<>();
public int getTotalActiveCount() {
return totalActiveCount;
}
public void setTotalActiveCount(int totalActiveCount) {
this.totalActiveCount = totalActiveCount;
}
public int getTotalWaitingSize() {
return totalWaitingSize;
}
public void setTotalWaitingSize(int totalWaitingSize) {
this.totalWaitingSize = totalWaitingSize;
}
public Map<String, ThreadPoolInfo> getInfos() {
return infos;
}
public void setInfos(Map<String, ThreadPoolInfo> infos) {
this.infos = infos;
}
public void appendActiveCount(int activeCount) {
this.totalActiveCount += activeCount;
}
public void appendWaitingSize(int waitingSize) {
this.totalWaitingSize += waitingSize;
}
}