Java里的线程池在平日的工作用的不算少,特别是有大量数据需要多线程处理的情形,那么大家在用之前是不是该刨根问底呢?
我们知道,线程池不光是Java里有涉及,各大开源框架、中间件、数据库等都会设计不同类型的线程池,比如Dubbo、Tomcat、MySQL等等等,因为使用线程池的好处如下:
- 通过重复利用已经创建的线程降低线程创建和销毁带来的性能损耗;
- 提高任务的响应速度,任务不需要等待线程创建就能执行,因为利用池中已有的线程;
- 增加了线程的可控性,线程如果无限创建,将严重消耗系统资源,那么可以使用线程池对线程统一分配和监控,使线程数量在健康的状态下。
线程池的实现原理
向线程池提交一个任务后,线程池的处理逻辑如下:
- 任务提交,执行execute方法后,检查当前运行的线程数据量是否达到核心线程池的大小,如果未达到,则创建新的线程去处理任务,否则进行第2步;
- 核心线程池满了后,任务将放置在同步队列中,等待核心线程的处理,即第4步。如果同步队列中存储的任务已经满了,将进行第3步;
- 同步队列满了后,则创建新的线程来处理任务,直到线程数量达到最大线程数量时,则进行第5步;
- 核心线程反复的从同步队列中拉取任务处理;
- 当前运行的线程数超过maximumPoolSize,任务将被拒绝,并执行拒绝策略(RejectedExecutionHandler)。
线程池的创建
我们可用通过ThreadPoolExecutor来创建定制化的线程池,如下:
new ThreadPoolExecutor(corePoolSize,maximumPoolSize,KeepAliveTime,milliseconds,runnableTaskQueue,handler);
参数的含义如下:
- 1、corePoolSize:核心线程数,任务进入线程池时,不管有无空闲的线程都会建立新的线程处理,直到线程数达到核心线程数。可通过方法直接使线程池建立核心线程数的线程(预热)。
- 2、maximumPoolSize:最大线程数,线程池的任务队列满时,可继续创建线程数至最大线程数。任务队列无边界时,此参数无意义。
- 3、keepAliveTime:除核心线程外的空闲线程保持存活时间,如果任务很多,并且任务执行的时间较短,则可以适当的调大线程的存活时间,提高线程的利用率。
- 5、milliseconds:线程保持存活的时间单位,这里以毫秒为单位。
6、runnableTaskQueue:任务队列,用来保存等待执行的任务的阻塞队列。可用以下阻塞队列实现: