Java 线程池 ThreadPoolExecutor 的那些事儿

2021年11月24日 阅读数:5
这篇文章主要向大家介绍Java 线程池 ThreadPoolExecutor 的那些事儿,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

##线程池基础知识 ThreadPoolExecutor : 一个线程池 Executors : 线程池工厂,经过该类能够取得一个拥有特定功能的线程池 ThreadPoolExecutor类实现了Executor接口,所以经过这个接口,任何的Runnable对象均可以被ThreadPoolExecutor线程池调度。 常见的线程池类型java

  • public static ExecutorService newFixedThreadPool(int nThreads)
    

    返回一个固定线程数量的线程池。线程数量始终不变。当有空闲线程时,当即执行;若没有,新线程暂存在一个任务队列中,待线程空闲,便开始处理任务队列中的任务。函数

  • public static ExecutorService newSingleThreadExecutor()
    

    返回一个只有一个线程的线程池。新线程过来存放在任务队列中,线程空闲时,处理任务队列中的任务。性能

  • public static ExecutorService newCachedThreadPool()
    

    返回一个能够根据实际状况调整线程数量的线程池。线程的进程数不肯定,可是若是有空闲线程能够复用,则会优先使用该线程。若是全部线程都在工做,又有新的任务提交,那么就会建立新的线程执行任务。全部线程在当前任务完成以后,将返回线程池进行服用。spa

  • public static ScheduledExecutorService newSingleThreadScheduldExecutor()
    

    返回一个ScheduledExecutorService对象,线程池大小为1。在某个固定的延时以后执行,或者周期性执行某个任务线程

  • public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
    

    和上面同样,可是能够指定线程数。code


核心线程池的内部实现

对于核心的几个线程池,其内部实现都是使用了ThreadPoolExecutor实现。对象

  • public static ExecutorService newFixedThreaPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads,nThreads,
                                     0L,TimeUnit.SECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    
  • public static ExecutorService newSingleThreadExecutor() {
        return new ThreadPoolExecutor(1,1,
                                     0L,TimeUnit.SECONDS,
                                     new LinkedBlockingQueue<Runnable>());
    }
    
  • public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0,Integer.MAX_VALUE,
                                     60L,TimeUnit.SECONDS,
                                     new SynchronousQueue<Runnable>());
    }
    

看一下ThreadPoolExecutor最重要的构造函数接口

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long KeepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

函数的参数含义以下:队列

  • corePoolSize:线程池中的线程数量。
  • maximumPoolSize:线程池中的最大线程数量。
  • keepAliveTime:当线程池数量超过corePoolSize时,多余的空闲线程的存活时间。
  • unitkeepAliveTime的单位。
  • workQueue:任务队列,被提交可是还没有被执行的任务。
  • threadFactory:线程工厂,用于建立线程,通常用默认的就行。
  • handler:拒绝策略。当任务太多来不及处理,如何拒绝任务。

在上面的参数中,其余的都好理解,主要是workQueuehandler须要重点说起一下。进程


###workQueue 任务队列讲解

workQueue 指被提交可是还没有被执行的任务队列,它是一个BlockingQueue接口的对象,仅用于存在Runnable对象。根据队列功能分类,在ThreadPoolExecutor的构造函数中能够使用如下几种BlockingQueue

  • 直接提交的队列SynchronousQueueSychronousQueue是一个特殊的BlockingQueueSychronousQueue没有容量,每个插入操做都要等待一个相应的删除操做,反之,一个删除操做都要等待对应的插入操做。若是使用SychronousQueue,提交的任务不会被真实的保存,而老是将新任务提交给线程执行,若是没有空闲线程,那么尝试建立新的线程,若是进程数量已经达到最大值,则执行拒绝策略。所以,使用SychronousQueue一般要设置很大的maximumcorePoolSize,不然很容易执行拒绝策略。
  • 有界的任务队列ArrayBlockingQueue:特色:如有新的任务须要执行,若是线程池的实际线程小于corePoolSize,则会优先建立新的线程;若大于corePoolSize,则会将新任务加入到等待队列。若是等待队列已满,没法加入,则在总线成熟不大于maximumPoolSize的前提下,建立新的线程执行任务。若大于,则执行拒绝策略。
  • 无界的任务队列LinkedBlockingQueue:特色:如有新的任务须要执行,若是线程池的实际线程小于corePoolSize,则会优先建立新的线程;若大于corePoolSize,进入等待队列。
  • 优先任务队列PriorityBlockingQueue:能够根据任务自身的优先级顺序前后执行。

###handler拒绝策略讲解

JKD 内置的拒绝策略都是经过实现RejectedExecutionHandler接口实现的,具体以下:

  • AbortPolicy策略:直接抛出异常,阻止系统正常工做;
  • CallerRunsPolicy策略:只要线程未关闭,直接在调用者线程中,运行当前被丢弃的任务。warning:有可能性能会急剧降低
  • DiscardOledstPolicy策略:丢弃一个最老的请求,并尝试再次提交当前的任务。
  • DiscardPolicy策略:丢弃没法处理的请求,不予任何处理,不作出任何的提示。