所谓的线程池的 7 大参数是指,在应用 ThreadPoolExecutor 创立线程池时所设置的 7 个参数,如以下源码所示:

public ThreadPoolExecutor(int corePoolSize,                          int maximumPoolSize,                          long keepAliveTime,                          TimeUnit unit,                          BlockingQueue<Runnable> workQueue,                          ThreadFactory threadFactory,                          RejectedExecutionHandler handler) {    //...}

这 7 个参数别离是:

  1. corePoolSize:外围线程数。
  2. maximumPoolSize:最大线程数。
  3. keepAliveTime:闲暇线程存活工夫。
  4. TimeUnit:工夫单位。
  5. BlockingQueue:线程池工作队列。
  6. ThreadFactory:创立线程的工厂。
  7. RejectedExecutionHandler:回绝策略。

    参数1:corePoolSize

    外围线程数:是指线程池中长期存活的线程数。

    这就好比现代大户人家,会长期雇佣一些“短工”来给他们干活,这些人个别比较稳定,无论这一年的活多活少,这些人都不会被解雇,都是长期生存在大户人家的。

参数2:maximumPoolSize

最大线程数:线程池容许创立的最大线程数量,当线程池的工作队列满了之后,能够创立的最大线程数。

这是现代大户人家最多能够雇佣的人数,比方某个节日或大户人家有人过寿时,因为活太多,仅靠“短工”是完不成工作,这时就会再招聘一些“短工”一起来干活,这个最大线程数就是“短工”+“短工”的总人数,也就是招聘的人数不能超过 maximumPoolSize。

注意事项

最大线程数 maximumPoolSize 的值不能小于外围线程数 corePoolSize,否则在程序运行时会报 IllegalArgumentException 非法参数异样,如下图所示:

参数3:keepAliveTime

闲暇线程存活工夫,当线程池中没有工作时,会销毁一些线程,销毁的线程数=maximumPoolSize(最大线程数)-corePoolSize(外围线程数)。

还是以大户人家为例,当大户人家比较忙的时候就会雇佣一些“短工”来干活,但等干完活之后,不忙了,就会将这些“短工”解雇掉,而 keepAliveTime 就是用来形容没活之后,短工能够在大户人家待的(最长)工夫。

参数4:TimeUnit

工夫单位:闲暇线程存活工夫的形容单位,此参数是配合参数 3 应用的。
参数 3 是一个 long 类型的值,比方参数 3 传递的是 1,那么这个 1 示意的是 1 天?还是 1 小时?还是 1 秒钟?是由参数 4 说了算的。
TimeUnit 有以下 7 个值:

  1. TimeUnit.DAYS:天
  2. TimeUnit.HOURS:小时
  3. TimeUnit.MINUTES:分
  4. TimeUnit.SECONDS:秒
  5. TimeUnit.MILLISECONDS:毫秒
  6. TimeUnit.MICROSECONDS:奥妙
  7. TimeUnit.NANOSECONDS:纳秒

    参数5:BlockingQueue

    阻塞队列:线程池寄存工作的队列,用来存储线程池的所有待执行工作。
    它能够设置以下几个值:

  8. ArrayBlockingQueue:一个由数组构造组成的有界阻塞队列。
  9. LinkedBlockingQueue:一个由链表构造组成的有界阻塞队列。
  10. SynchronousQueue:一个不存储元素的阻塞队列,即间接提交给线程不放弃它们。
  11. PriorityBlockingQueue:一个反对优先级排序的无界阻塞队列。
  12. DelayQueue:一个应用优先级队列实现的无界阻塞队列,只有在提早期满时能力从中提取元素。
  13. LinkedTransferQueue:一个由链表构造组成的无界阻塞队列。与SynchronousQueue相似,还含有非阻塞办法。
  14. LinkedBlockingDeque:一个由链表构造组成的双向阻塞队列。

比拟罕用的是 LinkedBlockingQueue,线程池的排队策略和 BlockingQueue 非亲非故。

参数6:ThreadFactory

线程工厂:线程池创立线程时调用的工厂办法,通过此办法能够设置线程的优先级、线程命名规定以及线程类型(用户线程还是守护线程)等。
线程工厂的应用示例如下:

public static void main(String[] args) {    // 创立线程工厂    ThreadFactory threadFactory = new ThreadFactory() {        @Override        public Thread newThread(Runnable r) {            // 创立线程池中的线程            Thread thread = new Thread(r);            // 设置线程名称            thread.setName("Thread-" + r.hashCode());            // 设置线程优先级(最大值:10)            thread.setPriority(Thread.MAX_PRIORITY);            //......            return thread;        }    };    // 创立线程池    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 0,                                                                   TimeUnit.SECONDS, new LinkedBlockingQueue<>(),                                                                   threadFactory); // 应用自定义的线程工厂    threadPoolExecutor.submit(new Runnable() {        @Override        public void run() {            Thread thread = Thread.currentThread();            System.out.println(String.format("线程:%s,线程优先级:%d",                                             thread.getName(), thread.getPriority()));        }    });}

以上程序的执行后果如下:

从上述执行后果能够看出,自定义线程工厂起作用了,线程的名称和线程的优先级都是通过线程工厂设置的。

参数7:RejectedExecutionHandler

回绝策略:当线程池的工作超出线程池队列能够存储的最大值之后,执行的策略。
默认的回绝策略有以下 4 种:

  • AbortPolicy:回绝并抛出异样。
  • CallerRunsPolicy:应用以后调用的线程来执行此工作。
  • DiscardOldestPolicy:摈弃队列头部(最旧)的一个工作,并执行当前任务。
  • DiscardPolicy:疏忽并摈弃当前任务。

线程池的默认策略是 AbortPolicy 回绝并抛出异样。

总结

本文介绍了线程池的 7 大参数:

  1. corePoolSize:外围线程数,线程池失常状况下放弃的线程数,大户人家“短工”的数量。
  2. maximumPoolSize:最大线程数,当线程池忙碌时最多能够领有的线程数,大户人家“短工”+“短工”的总数量。
  3. keepAliveTime:闲暇线程存活工夫,没有活之后“短工”能够生存的最大工夫。
  4. TimeUnit:工夫单位,配合参数 3 一起应用,用于形容参数 3 的工夫单位。
  5. BlockingQueue:线程池的工作队列,用于保留线程池待执行工作的容器。
  6. ThreadFactory:线程工厂,用于创立线程池中线程的工厂办法,通过它能够设置线程的命名规定、优先级和线程类型。
  7. RejectedExecutionHandler:回绝策略,当任务量超过线程池能够保留的最大工作数时,执行的策略。

是非审之于己,毁誉听之于人,得失安之于数。

公众号:Java面试真题解析

面试合集:https://gitee.com/mydb/interview