线程池的优势
- 减少资源的开销:减少了每次创建线程和销毁线程的开销。
- 提高响应速度:每次请求到来时,由于线程已经创建完成,可以直接执行任务,提高了响应速度。
- 提高线程的可管理性:线程是一种稀缺资源,如果不进行管理,会造成很大的资源浪费,而且还会影响系统的稳定性。线程池对线程的创建、停止、数量等因素控制,保证线程正常运行的同时,还方便性能的调优。
线程池的实现原理
线程池由:工作线程队列和,阻塞队列构成。
工作队列:指一组已经处在运行中的队列,他们不断的在阻塞队列中领取任务。
阻塞队列:是用来存储来不及处理的任务。
创建线程池方法详解
new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,timeUnit,runableTaskQueue,Handler);
- corePoolSize:基本线程数量;表示线程池中运行的线程的数量值在这个上下波动。
- maximumPoolSize:最大线程数;这个是线程的上限,如果实际线程数量达到这个值并且阻塞队列未满,任务放在阻塞队列中,否则,阻塞队列已满,调用饱和策略。
- keeyAliveTime:线程空闲的最大时间,timeUnit是这个单位。
- runableTaskQueue:任务队列(阻塞队列);这是一个阻塞队列,通常有如下几种。
- ArrayBlockingQueue:是由数组实现的阻塞队列,是FIFO的原则。
- LinkedBlockingQueue:是由一个链表实现的阻塞队列,也是FIFO原则,在newFixedThreadPool使用的阻塞队列。他的吞吐量比ArrayBlockingQueue高,是一个无边界队列。
- SynchronousQueue:是一个没有任何存储空间的阻塞队列,任务提交给他们后必须交给一条线程处理,如果当前没有空闲线程,则立即创建一个新的工作线程。cacheThreadPool使用的阻塞队列就是他。
- PriorityBlockingQueue:他是一个优先权阻塞队列。
- handler:饱和策略;当实际线程数达到maximumPoolSize,并且阻塞队列已满时,就会调用饱和策略。有:AbortPolicy:默认直接抛异常;CallerRunPolicy:只调用者所在的线程执行任务。DiscardOlderPolicy:丢弃队列中最持久的任务。DiscardPolicy:丢弃当前任务。
提交任务
两种任务的提交方式:Runable,Callable;
Runable:没有返回值,只执行,并且在执行过程中不会抛出异常,通过execute提交。
Callable:有返回值,是Future类型,可以抛出异常,通过函数submit提交,可以通过get获取元素值。
关闭线程池
关闭线程池的方式有shutDown和shutDownNow,关闭时,会遍历所有的线程调用他们的interrupt函数进行关闭。
shutDown:只关闭阻塞队列中的线程,对已经正在执行的线程会让他们正常结束。
shutDownNow:他会关闭全部的线程,不管是阻塞队列的还是正在运行的,都会全部关闭掉。
ThreadPoolExecutor运行机制
请求来临时:①.当前的实际线程小于corePoolSzie,即使有空闲线程,也会创建一个新的工作线程;
②.若当前的实际线程在corePoolSize和maximumPoolSize之间,并且阻塞队列没有满,那么将任务之间放在阻塞队列中。
③.若当实际线程数量小于maximumPoolSize,但阻塞线程已经满了,则直接创建新线程处理任务。
④.若当实际线程数量已经达到maximumPoolSize并且阻塞队列已经满了,调用饱和策略。
设置线程池的大小
任务分为:CPU密集型(较小的线程池,核心数+1 )、IO密集型(较大的线程池,2*CPU核心数)、混合型 (将任务分成IO密集型和CPU密集型任务,,然后分别用不同的线程池去处理).