线程池
package com.sq.dispatcher.utils;
import com.sq.dispatcher.monitor.thread.LogThreadStore;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by yangnan on 2017/09/29.
* 代码和思路主要来自于:
* <p>
* tomcat :
* org.apache.catalina.core.StandardThreadExecutor
* <p>
* java.util.concurrent
* threadPoolExecutor execute执行策略: 优先offer到queue,queue满后再扩充线程到maxThread,如果已经到了maxThread就reject
* 比较适合于CPU密集型应用(比如runnable内部执行的操作都在JVM内部,memory copy, or compute等等)
* <p>
* StandardThreadExecutor execute执行策略: 优先扩充线程到maxThread,再offer到queue,如果满了就reject
* 比较适合于业务处理需要远程资源的场景
*
* @author yangnan
*/
public class StandardThreadExecutor extends ThreadPoolExecutor {
public static final int DEFAULT_MIN_THREADS = 20;
public static final int DEFAULT_MAX_THREADS = 200;
/**
* 1 minutes
*/
public static final int DEFAULT_MAX_IDLE_TIME = 60 * 1000;
/**
* 正在处理的任务数
*/
protected AtomicInteger submittedTasksCount;
/**
* 最大允许同时处理的任务数
*/
private int maxSubmittedTaskCount;
public StandardThreadExecutor() {
this(DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS);
}
public StandardThreadExecutor(int coreThread, int maxThreads) {
this(coreThread, maxThreads, maxThreads);
}
public StandardThreadExecutor(int coreThread, int maxThreads, long keepAliveTime, TimeUnit unit) {
this(coreThread, maxThreads, keepAliveTime, unit, maxThreads);
}
public StandardThreadExecutor(int coreThreads, int maxThreads, int queueCapacity) {
this(coreThreads, maxThreads, queueCapacity, Executors.defaultThreadFactory());
}
public StandardThreadExecutor(int coreThreads, int maxThreads, int queueCapacity, ThreadFactory threadFactory) {
this(coreThreads, maxThreads, DEFAULT_MAX_IDLE_TIME, TimeUnit.MILLISECONDS, queueCapacity, threadFactory);
}
public StandardThreadExecutor(int coreThreads, int maxThreads, long keepAliveTime, TimeUnit unit, int queueCapacity) {
this(coreThreads, maxThreads, keepAliveTime, unit, queueCapacity, Executors.defaultThreadFactory());
}
public StandardThreadExecutor(int coreThreads, int maxThreads, long keepAliveTime, TimeUnit unit,
int queueCapacity, ThreadFactory threadFactory) {
this(coreThreads, maxThreads, keepAliveTime, unit, queueCapacity, threadFactory, new AbortPolicy());
}
public StandardThreadExecutor(int coreThreads, int maxThreads, long keepAliveTime, TimeUnit unit,
int queueCapacity, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
super(coreThreads, maxThreads, keepAliveTime, unit, new ExecutorQueue(), threadFactory, handler);
((ExecutorQueue) getQueue()).setStandardThreadExecutor(this);
submittedTasksCount = new AtomicInteger(0);
// 最大并发任务限制: 队列buffer数 + 最大线程数
// 这种队列首先创建线程,其次放到任务队列
maxSubmittedTaskCount = queueCapacity + maxThreads;
LogThreadStore.addExecutor(this);
}
@Override
public void execute(Runnable command) {
int count = submittedTasksCount.incrementAndGet();
// 超过最大的并发任务限制,进行 reject
// 依赖的LinkedTransferQueue没有长度限制,因此这里进行控制
if (count > maxSubmittedTaskCount) {
submittedTasksCount.decrementAndGet();
getRejectedExecutionHandler().rejectedExecution(command, this);
}
try {
super.execute(command);
} catch (RejectedExecutionException rx) {
// there could have been contention around the queue
if (!((ExecutorQueue) getQueue()).force(command)) {
submittedTasksCount.decrementAndGet();
getRejectedExecutionHandler().rejectedExecution(command, this);
}
}
}
public int getSubmittedTasksCount() {
return this.submittedTasksCount.get();
}
public int getMaxSubmittedTaskCount() {
return maxSubmittedTaskCount;
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
submittedTasksCount.decrementAndGet();
}
}
/**
* LinkedTransferQueue 能保证更高性能,相比与LinkedBlockingQueue有明显提升
* <p>
* <pre>
* 1) 不过LinkedTransferQueue的缺点是没有队列长度控制,需要在外层协助控制
* </pre>
*
* @author yangnan
*/
class ExecutorQueue extends LinkedTransferQueue<Runnable> {
private static final long serialVersionUID = -265236426751004839L;
StandardThreadExecutor threadPoolExecutor;
public ExecutorQueue() {
super();
}
public void setStandardThreadExecutor(StandardThreadExecutor threadPoolExecutor) {
this.threadPoolExecutor = threadPoolExecutor;
}
/**
* 注:代码来源于 tomcat
*/
public boolean force(Runnable o) {
if (threadPoolExecutor.isShutdown()) {
throw new RejectedExecutionException("Executor not running, can't force a command into the queue");
}
// forces the item onto the queue, to be used if the task is rejected
return super.offer(o);
}
/**
* 注:tomcat的代码进行一些小变更
*/
@Override
public boolean offer(Runnable o) {
int poolSize = threadPoolExecutor.getPoolSize();
// we are maxed out on threads, simply queue the object
if (poolSize == threadPoolExecutor.getMaximumPoolSize()) {
return super.offer(o);
}
// we have idle threads, just add it to the queue
// note that we don't use getActiveCount(), see BZ 49730
if (threadPoolExecutor.getSubmittedTasksCount() <= poolSize) {
return super.offer(o);
}
// if we have less threads than maximum force creation of a new
// thread
if (poolSize < threadPoolExecutor.getMaximumPoolSize()) {
return false;
}
// if we reached here, we need to add it to the queue
return super.offer(o);
}
}
监控
package com.sq.dispatcher.monitor.thread;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sq.dispatcher.constants.TraceConstant;
import com.sq.dispatcher.utils.NameThreadFactory;
import com.sq.dispatcher.utils.monitor.ThreadPoolMonitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
*
* @author yangnan
* @date 18/1/3
* 监控业务线程日志
*/
public class LogThreadStore {
private static final Logger MONITOR_LOGGER = LoggerFactory.getLogger(TraceConstant.MONITOR);
private static final Logger LOGGER = LoggerFactory.getLogger(LogThreadStore.class);
private static List<ThreadPoolExecutor> executorList = Lists.newArrayList();
private static volatile ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = null;
public static void addExecutor(ThreadPoolExecutor executor) {
synchronized (LogThreadStore.class) {
executorList.add(executor);
}
if (scheduledThreadPoolExecutor == null) {
init();
}
}
private static void init() {
if (scheduledThreadPoolExecutor == null) {
synchronized (LogThreadStore.class) {
if (scheduledThreadPoolExecutor == null) {
scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
}
}
}
scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
for (ThreadPoolExecutor executor : executorList) {
if (executor == null) {
continue;
}
store(executor);
}
}, 0, 10, TimeUnit.SECONDS);
}
private static void store(ThreadPoolExecutor poolExecutor) {
ThreadPoolMonitor threadPoolMonitor = new ThreadPoolMonitor(poolExecutor);
StringBuilder log = new StringBuilder(64);
try {
log.append("system=dispatcher").append("&");
log.append("metric=pool_executor").append("&");
String name = "default";
if (poolExecutor.getThreadFactory() instanceof NameThreadFactory) {
NameThreadFactory nameThreadFactory = (NameThreadFactory) poolExecutor.getThreadFactory();
log.append("name=").append(nameThreadFactory.getName()).append("&");
name = nameThreadFactory.getName();
} else {
log.append("name=").append("default").append("&");
}
log.append("active=").append(threadPoolMonitor.getActiveCount()).append("&");
log.append("completed_task=").append(threadPoolMonitor.getCompletedTaskCount()).append("&");
log.append("core_pool_size=").append(threadPoolMonitor.getCorePoolSize()).append("&");
log.append("largest_pool_size=").append(threadPoolMonitor.getLargestPoolSize()).append("&");
log.append("maximum_pool_size=").append(threadPoolMonitor.getMaximumPoolSize()).append("&");
log.append("queue_size=").append(threadPoolMonitor.getQueueSize()).append("&");
log.append("task=").append(threadPoolMonitor.getTaskCount()).append("&");
log.append("pool_size=").append(threadPoolMonitor.getPoolSize()).append("&");
MONITOR_LOGGER.info(log.deleteCharAt(log.length() -1 ).toString());
} catch (Exception e) {
LOGGER.error("store e.message:{}", e.getMessage(), e);
}
}
}
工具类
package com.sq.dispatcher.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author yangnan
* @date 18/1/17
*/
public class ThreadUtils {
private static ReentrantLock lock = new ReentrantLock();
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadUtils.class);
private static volatile ThreadPoolExecutor executor = null;
private static volatile StandardThreadExecutor standardExecutor = null;
private static final int CORE_SIZE = Runtime.getRuntime().availableProcessors();
private static final int MAX_SIZE = 5 * CORE_SIZE;
private static final int LARGEST_SIZE = 200;
private static final int QUEUE_SIZE = 20000;
private static final int KEEP_ALIVE_TIME = 60;
//兼容submit方法
static {
int maxSize = MAX_SIZE;
if (MAX_SIZE > LARGEST_SIZE) {
maxSize = LARGEST_SIZE;
}
executor = new ThreadPoolExecutor(CORE_SIZE, maxSize, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new LinkedBlockingQueue<>(QUEUE_SIZE), new NameThreadFactory("threadCommon"));
executor.allowCoreThreadTimeOut(true);
Runtime.getRuntime().addShutdownHook(new Thread(() -> shutDown()));
}
/**
* io密集型
*
* @return
*/
public static StandardThreadExecutor getStandardExecutorInstance() {
if (null == standardExecutor) {
lock.lock();
try {
if (null == standardExecutor) {
int maxSize = getMaxThreadSize();
int coreSize = 2 * CORE_SIZE;
LOGGER.info("standardExecutor线程池信息,核心线程数=[{}],最大线程数=[{}],空闲有效时间=[{}],队列容量=[{}]",
coreSize, maxSize, KEEP_ALIVE_TIME, QUEUE_SIZE);
standardExecutor = new StandardThreadExecutor(coreSize, maxSize, KEEP_ALIVE_TIME, TimeUnit.SECONDS, QUEUE_SIZE, new NameThreadFactory("threadCommon"));
standardExecutor.allowCoreThreadTimeOut(true);
Runtime.getRuntime().addShutdownHook(new Thread(() -> shutDownStand()));
}
} finally {
lock.unlock();
}
}
return standardExecutor;
}
public static void submit(Runnable task) {
executor.submit(task);
}
@Deprecated
public static <V> Future<V> submit(Callable<V> task) {
return executor.submit(task);
}
@Deprecated
public static <V> Future<V> submit(Runnable task, V v) {
return executor.submit(task, v);
}
public static void shutDown() {
LOGGER.info("关闭线程池...");
if (executor != null) {
executor.shutdown();
executor = null;
}
}
public static void shutDownStand() {
LOGGER.info("关闭线程池...");
if (standardExecutor != null) {
standardExecutor.shutdown();
standardExecutor = null;
}
}
/**
* 最大线程数
*
* @return
*/
private static int getMaxThreadSize() {
int maxSize = MAX_SIZE;
if (MAX_SIZE > LARGEST_SIZE) {
maxSize = LARGEST_SIZE;
}
return maxSize;
}
}