我还记得大学实习面试时,被问到什么是线程池这个问题,因为这个题我被录取了,原因就是我背出来了,而另外一个面试的没背出来,说实话当时还真不知道它是干什么的,就是看面试题给背下来了,在之后就是在实际开发中,确实使用到了。
首先说什么是线程池,为什么使用线程池?线程池就是提前创建若干个线程,如果有任务需要处理,线程池里的线程就会处理任务,处理完之后线程并不会被销毁,而是等待下一个任务。由于创建和销毁线程都是消耗系统资源的,所以当你想要频繁的创建和销毁线程的时候就可以考虑使用线程池来提升系统的性能。
Java中有三个比较常用的线程池,分别是FixedThreadPool,SingleThreadExecutor,CachedThreadPool。
1)FixedThreadPool

FixedThreadPool
这是一个线程数固定的线程池,当这个线程池被创建的时候,池里的线程数就已经固定了。当需要运行的线程数量大体上变化不大时,适合使用这种线程池。固定数量还有一个好处,它可以一次性支付高昂的创建线程的开销,之后再使用的时候就不再需要这种开销。
2) SingleThreadExecutor

SingleThreadExecutor
这是一个线程数量为1的线程池,所有提交的这个线程池的任务都会按照提交的先后顺序排队执行。单个线程执行有个好处:由于任务之间没有并发执行,因此提交到线程池种的任务之间不会相互干扰。程序执行的结果更具有确定性。
3) CachedThreadPool

CachedThreadPool
一看到Cache就知道这是一个和缓存有关的线程池,每次有任务提交到线程池的时候,如果池中没有空闲的线程,线程池就会为这个任务创建一个线程,如果有空闲的线程,就会使用已有的空闲线程执行任务。有的人可能会有个疑惑:这样线程不就越来越多了吗?其实不是的,这个线程池还有一个销毁机制,如果一个线程60秒之内没有被使用过,这个线程就会被销毁,这样就节省了很多资源。
上面这3中在一般的小项目使用可以了,但是无限制的创建线程可能造成内存溢出,因为上面的队列都是无界限的,没有设置大小。还有拒绝策略可能你不想使用默认的(AbortPolicy)。拒绝策略如图:

拒绝策略
为什么说AbortPolicy是默认的,看下源码

ThreadPoolExecutor

AbortPolicy
比如小编的项目中,就自定义一个线程池。定义队列里的个数不能超过5个,策略还是使用默认策略,从上面的3中创建方式中,可以看得出他们都是通过ThreadPoolExecutor来创建的,所以我也是通过ThreadPoolExecutor来创建。

自定义

执行

结果
这样都队列满时,就会抛出异常。
总结:
1、线程池是一个典型的“用空间换时间”的应用案例,在线程池中始终维护一定数量的线程,这样不必每次都创建新的线程,代价是线程即使空闲的时候也要占用内存资源。当需要频繁创建和销毁线程的时候,使用线程池可以显著提高系统的运行效率。
2、自定义线程可以满足我们控制队列,避免造成内存溢出,也能满足我们设置对队列满时的拒绝策略。