下面先总结一下线程池相关的知识点:
关于线程池相关类的继承关系为:
ThreadPoolExecutor—extends—》AbstractExecutorService—implements—》ExecutorService(接口)—extends—》Executor(接口)
1.关于ThreadPoolExecutor对象的创建时相关的参数的含义:
下面详细说明:
共有四个构造函数,其中共同的参数为:
(1)corePoolSize:当前维护的线程数量,甚至包括闲置的线程
(2)maximumPoolSize:允许在线程池中维护的最大线程数量
(3)keepAliveTime:对于线程池中所维护的线程所允许的闲置时间
(4)unit:闲置时间的时间单位
(5)workQueue:线程池中所使用的线程任务缓冲队列
除了以上参数外其他几个不常用的构造函数中特有的参数的含义为:
(6)handler:当缓冲队列已满,并且达到了最大线程数量的时候,通过此参数来处理被拒绝的任务
(7)threadFactory:用来创建新的线程
下面单独解释一下参数handler具体的值的含义,共有四个:
- ThreadPoolExecutor.AbortPolicy()
抛出java.util.concurrent.RejectedExecutionException异常 - ThreadPoolExecutor.CallerRunsPolicy()
重试添加当前的任务,他会自动重复调用execute()方法
3.ThreadPoolExecutor.DiscardOldestPolicy()
抛弃旧的任务
4.ThreadPoolExecutor.DiscardPolicy()
抛弃当前的任务
2.下面说当由线程池去执行任务的时候各个参数之间的关系,也就是线程池的执行原理:
先说一下以下几个参数的优先级,也就是下面几个参数的使用顺序:
从低到高依次为:corePoolSize——》workQueue——》maximumPoolSize——》handler。
(1)当一个任务(Runnable)被执行时,通过调用execute(Runnable runnable)方法,此时当线程池中的线程数量小于corePoolSize时,即使有闲置线程首先会在线程池中创建一个新的线程去执行此任务。
(2)随着任务数量的增加,当线程池中线程的数量等于corePoolSize,并且workQueue缓冲队列未满时,会将新增加的任务缓存到workQueue中,此时线程池中闲置的线程回去workQueue中获取任务并执行。
(3)当workQueue缓冲队列已满,但是线程池中的线程数量小于maximumPoolSize时,会在线程池中创建新的线程去执行当前任务。
(4)当线程池中的线程数量等于maximumPoolSize时,此时会将任务交由handler去处理,按照相应的处理策略。
此时也就可以看出使用线程池来管理线程的优点:
当线程池中线程的数量大于corePoolSize时,如果某个线程到了闲置时间,会被自动销毁,使得线程池可以动态的控制线程的数量。
当然还有几个特殊的线程池对象我在这里就不介绍了,原理都是大同小异。
最后举例说明单一原则(SRP)和开闭原则(OCP)的具体体现:其中单一原则很多时候界限不是很明确,但是它也是有一定的规则:例如1:要保证类和方法的职责单一,也就是说一个类一个方法只做一件事。
其中开闭原则指的是类只可以通过继承的方式进行扩展,绝不允许去修改它,除非这个类里面有明显的错误。但事实上在实际开发中很难做到,通常修改和继承时同时存在的。我的理解不是很深,望大家多提宝贵的建议,我们共同进步,今天就写到这里。