[面试] 线程池相关

建立线程池的四种方式

  1. CachedThreadPool建立一个可缓存线程池,若是线程池长度超过处理须要,可灵活回收空闲线程,若无可回收,则新建线程。
  2. FixedThreadPool 建立一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  3. ScheduledThreadPool 建立一个定长线程池,支持定时及周期性任务执行。
  4. SingleThreadExecutor 建立一个单线程化的线程池,它只会用惟一的工做线程来执行任务,保证全部任务按照指定顺序(FIFO, LIFO, 优先级)执行。

建立线程池的七个参数

image
从源码中能够看出,线程池的构造函数有7个参数,分别是corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。下面会对这7个参数一一解释。数组

  1. corePoolSize 线程池核心线程大小
    线程池中会维护一个最小的线程数量,即便这些线程处理空闲状态,他们也不会 被销毁,除非设置了allowCoreThreadTimeOut。这里的最小线程数量便是corePoolSize。
  2. maximumPoolSize 线程池最大线程数量
    一个任务被提交到线程池后,首先会缓存到工做队列(后面会介绍)中,若是工做队列满了,则会建立一个新线程,而后从工做队列中的取出一个任务交由新线程来处理,而将刚提交的任务放入工做队列。线程池不会无限制的去建立新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize来指定。
  3. keepAliveTime 空闲线程存活时间
    一个线程若是处于空闲状态,而且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定
  4. unit 空间线程存活时间单位
    keepAliveTime的计量单位
  5. workQueue 工做队列
    新任务被提交后,会先进入到此工做队列中,任务调度时再从队列中取出任务。jdk中提供了四种工做队列:

    ①ArrayBlockingQueue
    基于数组的有界阻塞队列,按FIFO排序。新任务进来后,会放到该队列的队尾,有界的数组能够防止资源耗尽问题。当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。若是队列已是满的,则建立一个新线程,若是线程数量已经达到maxPoolSize,则会执行拒绝策略。
    ②LinkedBlockingQuene
    基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。因为该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去建立新线程直到maxPoolSize,所以使用该工做队列时,参数maxPoolSize实际上是不起做用的。
    ③SynchronousQuene
    一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。也就是说新任务进来时,不会缓存,而是直接被调度执行该任务,若是没有可用线程,则建立新线程,若是线程数量达到maxPoolSize,则执行拒绝策略。
    ④PriorityBlockingQueue
    具备优先级的无界阻塞队列,优先级经过参数Comparator实现。缓存

  6. threadFactory 线程工厂
    建立一个新线程时使用的工厂,能够用来设定线程名、是否为daemon线程等等
  7. handler 拒绝策略
    当工做队列中的任务已到达最大限制,而且线程池中的线程数量也达到最大限制,这时若是有新任务提交进来,该如何处理呢。这里的拒绝策略,就是解决这个问题的,jdk中提供了4中拒绝策略:并发

    • ①CallerRunsPolicy 该策略下,在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务。
    • ②AbortPolicy 该策略下,直接丢弃任务,并抛出RejectedExecutionException异常。
    • ③DiscardPolicy 该策略下,直接丢弃任务,什么都不作。
    • ④DiscardOldestPolicy 该策略下,抛弃进入队列最先的那个任务,而后尝试把此次拒绝的任务放入队列
相关文章
相关标签/搜索