线程池原理:用指定数量的线程,执行大量的线程任务
线程池作用:
假设目前有1000个任务需要执行,电脑的CPU核心为4,没有其他任务使用CPU。
那么有如下方式可以执行上述任务:
1、使用单个线程线性的执行1000个任务
缺点:不能最大程度的使用CPU,将会有3个CPU核心空闲,而且如果任务涉及IO读写等原因导致CPU中断,那么效率将极其低下。
2、每个任务过来,开启一个线程
缺点:如果每个任务的执行时间非常非常短,那么可以使用这种模式,如果每个任务执行非常长,最差的情况就是1000个线程共用4个CPU核心,这样导致非常频繁的上下文切换,每次切换涉及当前线程的CPU寄存器,虚拟内存的保存,然后唤醒另外一个线程,恢复该线程的上下文。
3、开启4个线程,每个线程监视任务,如果任务过来,将使用该线程执行任务,然后继续监视任务。
优点:合理的利用CPU,发挥最大性能
对于线程池具体需要开启多少个线程合理,个人认为需要考虑如下几点:
1、程序运行的环境,主要是看CPU参数
2、线程将要执行的任务情况:是属于计算型,还是IO读写,网络传输型
3、当前程序开启的线程情况。
ThreadPoolExecutor 简单解读:
ThreadPoolExecutor是个线程池的实现,有如下几个参数:
1、BlockingQueue<Runnable> workQueue 任务集合,如果workQueue指定了容量大小为N,那么当workQueue 的当前大小等于N时,每次任务过来将会开启一个工作线程,如果开启的工作线程大于maximumPoolSize,那么会调用reject方法,默认是忽略该任务,用户可以指定任何处理。
2、HashSet<Worker> workers 当前的工作线程
3、volatile long keepAliveTime 当大于corePoolSize的线程空闲该时间,将销毁
4、volatile int corePoolSize 工作线程的核心数量,任务过来,如果poolSize<corePoolSize那么将会新建一个工作线程,核心线程不会被销毁
5、volatile int maximumPoolSize 工作线程的最大数量
6、volatile int poolSize 当前工作线程数量
7、volatile RejectedExecutionHandler handler 当任务被拒绝时调用的处理器
注意点:
新建工作线程的条件:
1、当前工作线程小于corePoolSize时
2、当workQueue满了且当前工作线程小于maximumPoolSize的时候
何时任务被拒绝:
1、workQueue满了,并且poolSize == maximumPoolSize
shutdownNow 和 shutdown 区别:
shutdownNow 是立即关闭当前所有线程,然后返回没有执行完的工作任务
shutdown 是先关闭线程池中非当前工作线程,停止接收新的任务,等任务执行完后关闭。