Java-Concurrent 线程池ThreadPoolExecutor使用

 

    在高并发场景下,如果每一个请求或人物都开启一个线程,系统要不断的进行线程的创建、销毁,会消耗大量的系统性能,而线程的数量到达一个临界值时,系统会受到进一步更大的影响,这时候就需要用到线程池。

    ThreadPoolExecutor线程池的类关系

    Executor的定义是An Object that executes submitted tasks,即接口的实现是一个“执行提交任务”的对象,接口提供了一个将“任务提交”和“执行机制”分离的方法,包括线程使用详情,调度等。总之是提供了一个提交Runnable任务的接口。

    ExecutorService接口继承子Executor,提供了任务提交,执行,线程控制的一系列方法。

    AbstractExecutorService是ExecutorService的默认实现,提供了任务提交,管理的默认实现。

    ThreadPoolExecutor继承自AbstractExecutorService,是线程池的真正实现,通过构造方法的参数来配置生成不同的线程池,构造方法有:

    public ThreadPoolExecutor(int corePoolSize,

                              int maximumPoolSize,

                              long keepAliveTime,

                              TimeUnit unit,

                              BlockingQueue<Runnable> workQueue);

    public ThreadPoolExecutor(int corePoolSize,

                              int maximumPoolSize,

                              long keepAliveTime,

                              TimeUnit unit,

                              BlockingQueue<Runnable> workQueue,

                              ThreadFactory threadFactory) ;

    public ThreadPoolExecutor(int corePoolSize,

                              int maximumPoolSize,

                              long keepAliveTime,

                              TimeUnit unit,

                              BlockingQueue<Runnable> workQueue,

                              RejectedExecutionHandler handler);

    public ThreadPoolExecutor(int corePoolSize,

                              int maximumPoolSize,

                              long keepAliveTime,

                              TimeUnit unit,

                              BlockingQueue<Runnable> workQueue,

                              ThreadFactory threadFactory,

                              RejectedExecutionHandler handler);

 

    构造方法参数说明

   1) corePoolSize,核心线程数,通常情况下会一直存活,不会受keepAliveTime的控制,即使是idle的空闲状态,除非设置

allowCoreThreadTimeOut为true。

    2)maximumPoolSize,线程池最大线程数,线程池线程数达到这个数字,创建想成会被阻塞。任务队列为没有设置大小的LinkedBlockingDeque时,配置无效。

    3)keepAliveTime,非核心且idle(空闲)状态的线程存活时间,超过这个时间就会被回收。

    4)unit,keepAliveTime时间的单位

    5)workQueue,线程池的任务队列,常用的任务队列有SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue

    6)threadFactory,线程创建工厂,用于创建新线程,定制个性化线程参数,一般使用DefaultThreadFactory 默认实现

    7)RejectedExecutionHandler ,线程池的资源已全部被使用,添加线程失败后,执行rejectedExecution方法

    线程池创建参数配置

    当线程池任务队列无限大时

  • 如果线程数量<=核心线程数量,那么直接启动一个核心线程来执行任务,不会放入队列中。
  • 如果线程数量>核心线程数,但<=最大线程数,并且任务队列是LinkedBlockingDeque的时候,超过核心线程数量的任务会放在任务队列中排队。
  • 如果线程数量>核心线程数,但<=最大线程数,并且任务队列是SynchronousQueue的时候,线程池会创建新线程执行任务,这些任务也不会被放在任务队列中。这些线程属于非核心线程,在任务完成后,闲置时间达到了超时时间就会被清除。
  • 如果线程数量>核心线程数,并且>最大线程数,当任务队列是LinkedBlockingDeque,会将超过核心线程的任务放在任务队列中排队。也就是当任务队列是LinkedBlockingDeque并且没有大小限制时,线程池的最大线程数设置是无效的,他的线程数最多不会超过核心线程数。
  • 如果线程数量>核心线程数,并且>最大线程数,当任务队列是SynchronousQueue的时候,会因为线程池拒绝添加任务而抛出异常。

    当线程池任务队列有大小限制时

  • 当LinkedBlockingDeque塞满时,新增的任务会直接创建新线程来执行,当创建的线程数量超过最大线程数量时会抛异常。
  • SynchronousQueue没有数量限制。因为他根本不保持这些任务,而是直接交给线程池去执行。当任务数量超过最大线程数时会直接抛异常。

    Executors线程池工厂、工具类提供了一些个性化的线程池配置,如:

newFixedThreadPool(int nThreads)

ExecutorService newSingleThreadExecutor()

ExecutorService newCachedThreadPool()

ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)

  • newFixedThreadPool,可重用、固定线程的线程池,基于共享的、无限的队列,在任何时候,线程都是活动状态,且可以处理任务,如果在所有线程都是活动状态时提交任务,任务将缓存在任务队列中等待,知道线程空闲下来,如果由于执行期间线程挂掉,将会创建新的线程执行任务。
  • newSingleThreadExecutor,只有一个线程的线程池,基于无限队列,独苗线程挂掉后会重新创建,保证任务按照顺序执行,在任何给定时间,不会有多个任务处于活动状态
  • newCachedThreadPool,根据需要创建新线程的线程池,但是线程可以重用,通常用于执行许多短期异步任务, 如果没有现有线程可用,则为新线程将创建线程并将其添加到池中。 线程未使用60秒将被终止并从中删除缓存。
  • newScheduledThreadPool,延迟执行或定时执行任务的线程池。

(完)

猜你喜欢

转载自blog.csdn.net/weihao_/article/details/81983015