IO密集型线程池

线程池

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;
    }
}
发布了177 篇原创文章 · 获赞 14 · 访问量 47万+

猜你喜欢

转载自blog.csdn.net/qian_348840260/article/details/87373261