Java线程池的使用

概述:在一些场景下,我们使用多线程去解决一些高并发的问题,实现起来很方便。但是会有一些问题,如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。

那么,有没有一种办法可以使得线程复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?
答案是有的,通过线程池可以达到这样的效果,线程池最核心的类是ThreadPoolExecutor,那就先从这个类说起吧。

1. ThreadPoolExecutor类中四个构造方法

首先捋一下ThreadPoolExecutor类的继承关系:
在这里插入图片描述
从图中可以看出,ThreadPoolExecutor继承了AbstractExecutorService类,而AbstractExecutorService实现了ExecutorService接口,ExecutorService接口又继承了Executor接口,Executor接口中只定义了一个方法void execute(Runnable command)。

  • 该类主要有四个构造方法,先来看一下源码,以下是构造方法1:
    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default thread factory and rejected execution handler.
     * It may be more convenient to use one of the {@link Executors} factory
     * methods instead of this general purpose constructor.
     * 创建一个给定初始化参数、默认线程工厂和默认拒绝执行处理程序的ThreadPoolExecutor。
     * 使用Executors工厂方法之一而不是这个通用构造方法可能更方便。
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set  
     * 线程池核心线程数,如果空闲也一直保持在线程池中的线程数,除非设置了
     * allowCoreThreadTimeOut属性值
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * 线程池最大能容忍的线程数
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * 表示线程没有任务执行时最多保持多久时间会销毁
     * @param unit the time unit for the {@code keepAliveTime} argument
     * 表示keepAliveTime的时间单位,有7种值,可以从TimeUnit类种获取
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * 表示一个阻塞队列,用来存储等待执行的任务,常用有3种队列:
     * ArrayBlockingQueue
     * LinkedBlockingQueue
     * SynchronousQueue
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
  • 构造方法2,相比构造方法1多了一个可传参数threadFactory:
 /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default rejected execution handler.
     * 创建一个给定初始化参数和默认拒绝执行处理程序的ThreadPoolExecutor
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * 线程池核心线程数,如果空闲也一直保持在线程池中的线程数,除非设置了
     * allowCoreThreadTimeOut属性值
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * 最大能容忍的线程数
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * 表示线程没有任务执行时最多保持多久时间将会终止,直至达到不小于核心线程数
     * @param unit the time unit for the {@code keepAliveTime} argument
     * keepAliveTime的时间单位,有7种值,可从TimeUnit类中获取
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * 一个阻塞队列,用来存储等待执行的任务,一般有以下3种:
     * ArrayBlockingQueue
     * LinkedBlockingQueue
     * SynchronousQueue
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * 线程工厂,当executor创建一个新线程时用该工厂创建
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
  • 构造方法3,相比构造方法1多了一个可传入参数rejectedExecutionHandler:
/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default thread factory.
     * 创建一个给定初始化参数和默认的线程工厂的ThreadPoolExecutor
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * 线程池核心线程数,如果空闲也一直保持在线程池中的线程数,除非设置了
     * allowCoreThreadTimeOut属性值
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * 线程池中最大容忍线程数
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * 表示线程没有任务执行时最多保持多久时间将会终止,直至达到不小于核心线程数
     * @param unit the time unit for the {@code keepAliveTime} argument
     * keepAliveTime的时间单位,有7种值,可从TimeUnit类中获取
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * 一个阻塞队列,用来存储等待执行的任务,一般有以下3种:
     * ArrayBlockingQueue
     * LinkedBlockingQueue
     * SynchronousQueue
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * handler在执行被阻止时使用,因为达到了线程边界和队列容量
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
  • 构造方法4,相比构造方法1多了两个可传入参数threadFactory和rejectedExecutionHandler:
/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     * 创建一个给定初始化参数的ThreadPoolExecutor
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * 线程池核心线程数,如果空闲也一直保持在线程池中的线程数,除非设置了
     * allowCoreThreadTimeOut属性值
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * 线程池中最大容忍线程数
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * 表示线程没有任务执行时最多保持多久时间将会终止,直至达到不小于核心线程数
     * @param unit the time unit for the {@code keepAliveTime} argument
     * keepAliveTime的时间单位,有7种值,可从TimeUnit类中获取
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * 一个阻塞队列,用来存储等待执行的任务,一般有以下3种:
     * ArrayBlockingQueue
     * LinkedBlockingQueue
     * SynchronousQueue
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * 线程工厂,当executor创建一个新线程时用该工厂创建
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * handler在执行被阻止时使用,因为达到了线程边界和队列容量
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

2. 构造方法中参数的作用

  • corePoolSize: 核心池线程数,默认情况下线程池中的线程数为0(除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,是预创建线程的意思),当有任务到来之后,就会创建一个线程去执行任务,当线程池中的线程数达到corePoolSize后,再新来任务就会放到缓存队列当中;
  • maximumPoolSize: 线程池中最大容忍线程数,这个参数也是一个非常重要的参数,它表示在线程池中最多能创建的线程数;
  • keepAliveTime: 表示线程空闲后保持多久时间会终止。默认情况下,当前线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize值。但是如果调用了allowCoreThreadTimeOut(true)方法,在线线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;
  • unit: 参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性,分别是:
    TimeUnit.DAYS;//天
    TimeUnit.HOURS;//小时
    TimeUnit.MINUTES;//分钟
    TimeUnit.SECONDS;//秒
    TimeUnit.MILLISECONDS;//毫秒
    TimeUnit.MICROSECONDS;//微妙
    TimeUnit.NANOSECONDS;//纳秒
  • workQueue: 一个阻塞队列,用来存储等待执行的任务,这个参数会对线程池的运行过程产生重大影响,一般有以下4种选择:
    ArrayBlockingQueue
    PriorityBlockingQueue
    LinkedBlockingQueue
    SynchronousQueue
    前两个使用比较少,常用的是LinkedBlockingQueue 和 SynchronousQueue;
  • threadFactory: 线程工厂,主要用来创建新的线程;
  • handler: 拒绝执行处理器(RejectedExecutionHandler),在执行被阻止时使用,因为达到了线程边界和队列容量,有以下4种选择:
    ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。
    ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
    ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
    ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

3. ThreadPoolExecutor类中其他几个重要的方法

  • execute(): 这个方法是在Executor接口中声明的,只是在ThreadPoolExecutor类中进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行;
  • submit(): 这个方法是在ExecutorService中声明的,在AbstractExecutorService类中就已经有了具体的实现,并没有在ThreadPoolExecutor中进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同的是,它能够返回任务执行的结果,返回结果类型为FutureTask;
  • shutdown(): 用来关闭线程池的,调用这个方法后,就不能在线程池添加任何任务,否则会报RejectedExecutionException异常,但是线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成后才会退出;
  • shutdownNow(): 关闭线程池,迫使线程池中所有线程执行退出,从而让主程序正常退出。但并不代表线程池一定能立即退出,因为终止线程的方法是通过调用Thread.interrupt()方法实现的,如果线程中没有sleep、wait、Condition、定时锁等应用,interrupt()方法是无法中断当前线程的,它可能必须要等待所有正在执行的任务都执行完成了才能退出;

4. Executors工具类的使用

Executors类中提供了一些获取线程池的静态方法,以下是几个常用的方法:

  • newFixedThreadPool 固定大小线程池,简单来说就是每次提交一个任务就会创建一个线程,直到线程达到线程池的核心数大小,再来任务就会放到缓存队列中:
/**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue.  At any point, at most
     * {@code nThreads} threads will be active processing tasks.
     * If additional tasks are submitted when all threads are active,
     * they will wait in the queue until a thread is available.
     * If any thread terminates due to a failure during execution
     * prior to shutdown, a new one will take its place if needed to
     * execute subsequent tasks.  The threads in the pool will exist
     * until it is explicitly {@link ExecutorService#shutdown shutdown}.
     * 创建一个线程池,该线程池会重复使用在共享的无界队列中运行的固定数量的线程。 在任何时候,
     * 最多nThreads线程将是活动的处理任务。如果在所有线程都处于活动状态时提交了其他任务,
     * 则它们将在队列中等待,直到线程空闲可用。如果任何一个线程由于在关闭之前执行期间中出现故障而终止,
     * 那么如果需要执行后续任务,则新的线程将会取代它。线程池中的线程将一直存在,直到它被显式的shutdown。
     * @param nThreads the number of threads in the pool
     * 线程池的线程数
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
  • newSingleThreadExecutor 单线程执行的线程池,它相当于单线程 串行执行所有任务。如果这个唯一的线程因为异常而终止,那么会有一个新的线程来替代它。该线程池能保证所有任务的执行顺序是按照任务的提交顺序执行。值得注意的是:该线程从效果上和 newFixedThreadPool(1) 是一样的,但是返回时有一些区别,该线程池返回对象是经过FinalizableDelegatedExecutorService进行了包装,目的是为了在垃圾回收前销毁线程。
/**
     * Creates an Executor that uses a single worker thread operating
     * off an unbounded queue. (Note however that if this single
     * thread terminates due to a failure during execution prior to
     * shutdown, a new one will take its place if needed to execute
     * subsequent tasks.)  Tasks are guaranteed to execute
     * sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent
     * {@code newFixedThreadPool(1)} the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     * 创建一个Executor,它使用一个在无界队列中运行的工作线程。 
     *(但请注意,如果此单个线程由于在关闭之前执行期间出现故障而终止,则在需要执行后续任务时将使用新的线程。)
     * 保证任务顺序执行,并且在任何给定的时间内不会有多个任务处于活动状态。 
     * 与其他等效的例如:newFixedThreadPool(1) 不同,它保证返回的执行程序不可重新配置以使用其他线程。
     * @return the newly created single-threaded Executor
     */
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
static class FinalizableDelegatedExecutorService
        extends DelegatedExecutorService {
        FinalizableDelegatedExecutorService(ExecutorService executor) {
            super(executor);
        }
        //垃圾收集前会进行shutdown操作
        protected void finalize() {
            super.shutdown();
        }
    }
  • newCachedThreadPool 线程可缓存的线程池,corePoolSize设置为0,maximumPoolSize设置为Integer.MAX_VALUE
/**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available.  These pools will typically improve the performance
     * of programs that execute many short-lived asynchronous tasks.
     * Calls to {@code execute} will reuse previously constructed
     * threads if available. If no existing thread is available, a new
     * thread will be created and added to the pool. Threads that have
     * not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will
     * not consume any resources. Note that pools with similar
     * properties but different details (for example, timeout parameters)
     * may be created using {@link ThreadPoolExecutor} constructors.
     * 创建一个可根据需要来创建新线程的线程池,但在它们可用时将重复使用以前构造好的线程。 
     * 该线程池通常会提高执行许多短期异步任务的程序的性能。对execute的调用将重复使用以前构造好的线程(如果可用的话)。 
     * 如果没有可用的现有线程,则将创建一个新线程并将其添加到池中。未使用(空闲)60秒的线程将终止并从缓存中删除。 
     * 因此,长时间闲置的池不会消耗任何资源。请注意,也可以使用ThreadPoolExecutor构造方法自定义
     * 创建具有相似属性但不同详细信息的池(例如,超时参数)。
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • newScheduledThreadPool 创建一个ScheduledExecutorService线程池,该线程池可以实现定时、周期性执行任务,具体方法可以参考ScheduledExecutorService接口的实现类ScheduledThreadPoolExecutor;
	/**
     * Creates a thread pool that can schedule commands to run after a
     * given delay, or to execute periodically.
     * 创建一个线程池,可以调度命令,以在给定的延迟时间后运行,或者定期执行。
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle
     * 保持在线程池中的核心线程数,请注意,即使这些线程处于空闲状态也一直保持在线程池中
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

5. 项目中的实际运用

在实际的项目开发中,遇到需要异步处理的逻辑,可以使用Executors工具类去实现一个线程池(最好自己定义ThreadPoolExecutor来初始化一个线程池),然后提交一个任务去执行,我们可以根据不通的业务场景封装不同的线程池单例类,这样可以在不同场景使用相应的线程池(统一维护、管理、监控),以下是对Executors中部分方法封装的线程池单例类代码(通过内部类实现的单例模式):
为什么可以使用内部类实现单例模式?
JVM必须确保一个类在初始化的过程中,如果是多线程需要同时初始化它,仅仅只能允许其中一个线程对其执行初始化操作,其余线程必须等待,只有在活动线程执行完对类的初始化操作之后,才会通知正在等待的其他线程,所以可以利用静态内部类实现线程安全的单例模式。

/**
 * @Author: Helon
 * @Description: 常用的三种线程池,单例获取
 * @Data: Created in 2018/3/23 23:16
 * @Modified By:
 */
public class ThreadPoolSingleton {
    /**核心线程数,
     * 经验值设置,如果是CPU计算密集型应用设置为N+1或jdk1.8以上可设置为2N
     * 如果是IO密集型应用设置为N/(1-阻塞系数),阻塞系数一般为0.8~0.9之间(也可直接取0.8或0.9)其中N表示当前服务器的CPU核数
     */
    private static final int CORETHREADS = 10;

    /**
     * 1.默认创建的线程池corePoolSize和maximumPoolSize值是相等的;
     * 2.默认使用的是LinkedBlockingQueue队列,队列长度未指定,默认大小为Integer.MAX_VALUE
     * 3.默认keepAliveTime=0L,表示当前线程数大于corePoolSize时,空闲时间为0,即立即回收
     * 推荐使用
     */
    private static class NewFixedThreadPoolInstance {
        private static ExecutorService instance = Executors.newFixedThreadPool(CORETHREADS);
    }
    /**
     *newFixedThreadPool获取单例
     *
     */
    public static ExecutorService newFixedThreadPool(){
        return NewFixedThreadPoolInstance.instance;
    }
    
    /**
     * 1.默认创建的线程池corePoolSize和maximumPoolSize值是相等的,并且大小都为1;
     * 2.默认使用的是LinkedBlockingQueue队列,队列长度未指定,默认大小为Integer.MAX_VALUE
     * 3.默认keepAliveTime=0L,表示当前线程数大于corePoolSize时,空闲时间为0,即只要空闲立即销毁回收
     */
    private static class NewSingleThreadExecutorInstance {
        private static ExecutorService instance = Executors.newSingleThreadExecutor();
    }
    /**
     *newSingleThreadExecutor获取单例
     *
     */
    public static ExecutorService newSingleThreadPool(){
        return NewSingleThreadExecutorInstance.instance;
    }
    
    /**
     * 1.默认创建的线程池corePoolSize为0,,maximumPoolSize值为Integer.MAX_VALUE;
     * 2.默认使用的是SynchronousQueue队列,表示来了任务就创建线程运行
     * 3.默认keepAliveTime=60L,单位是秒,表示当线程空闲超过60秒,就销毁线程
     */
    private static class NewCachedThreadPoolInstance {
        private static ExecutorService instance = Executors.newCachedThreadPool();
    }
    
    /**
     *newCachedThreadPool获取单例
     *
     */
    public static ExecutorService newCachedThreadPool(){
        return NewCachedThreadPoolInstance.instance;
    }
	
	private ThreadPoolSingleton(){}
}
  • 这里对核心线程数简单说明一下,有个经验值:如果是CPU计算密集型应用(如:计算大量文件的大小),核心线程数=N+1,如果使用的jdk1.8及以上的可设置为2N(因为高版本jdk增加了并行计算);如果是IO密集型应用(如:大量网络传输,数据库访问等IO访问频繁的应用),核心线程数=N/(1-阻塞系数),这个阻塞系数一般为0.8~0.9。以上是经验值,并非绝对的,还需要根据实际情况以及实际业务来调整;
  • 到这里线程池的基本用法已经说的差不多了,然而实际项目中可能需要实时的了解一下线程池任务执行情况,这样应该怎么处理呢?我在项目中写了一个轮询查看线程池使用情况的任务,以下是我的实现代码:
/**
 * @Author: Helon
 * @Description: 线程池定时监控任务
 * @Data: Created in 2018/4/16 17:31
 * @Modified By:
 */
@Component
public class ThreadPoolMonitorTask {

    /***
     * 内部类初始化executor
     */
    private static class InitExecutorService {
        /**从线程池中获取newFixedThreadPool*/
        private static ExecutorService executorService = ThreadPoolSingleton.newFixedThreadPool();
    }

    /**
     * @Author: Helon
     * @Description: 初始化10s后开始执行,每隔30秒监控一次
     * @Data: 2018/4/16 17:50
     * @Modified By:
     */
    @Scheduled(initialDelay = 10000L, fixedDelay = 30000L)
    public void check() {
        ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor)InitExecutorService.executorService;
        LogUtil.KAFKA.info("[线程池定时监控]-核心池大小:{},最大线程数:{},当前线程数:{},当前活动线程数:{}",threadPoolExecutor.getCorePoolSize(),
                threadPoolExecutor.getMaximumPoolSize(), threadPoolExecutor.getPoolSize(), threadPoolExecutor.getActiveCount());
        LogUtil.KAFKA.info("[线程池定时监控]-总任务数:{},已经执行完毕的任务数:{},出现过最大的线程数:{}",threadPoolExecutor.getTaskCount(),
                threadPoolExecutor.getCompletedTaskCount(), threadPoolExecutor.getLargestPoolSize());
    }
}

好了,以上就是我对线程池的总结与使用,如有疑义的地方欢迎批评指正,一起交流学习。

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 、 1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,为适合; 4、下载使用后,可先查看READmE.文件(md如有),本项目仅用作交流学习参考,请切勿用于商业用途。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值