一、线程池的工作流程
1、线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。
2. 当调用 execute() 方法添加一个任务时,线程池会做如下判断:
如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列;
如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;
如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会根据拒绝策略来对应处理。
- 当一个线程完成任务时,它会从队列中取下一个任务来执行。
4. 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。
二、线程池主要参数有哪些?
线程池有七大参数,需要重点关注corePoolSize 、maximumPoolSize 、 workQueue 、handler 这四个。
1. corePoolSize
用来初始化线程池中核心线程数,当线程池中线程数<corePoolSize时,系统默认是添加一个任务才创建一个线程池。当线程数=corePoolSize时,新任务会追加到woreQueue中。
2. maximumPoolSize
maximumPoolSize表示允许的最大线程数=(非核心线程数+核心线程数),当BlockingQueue也满了,但线程池中的总线程数<maximumPoolSize时会再次创建新的线程。
3. keepAliveTime
非核心线程 =(maximumPoolSize - corePoolSize ) ,非核心线程闲置下来不干活最多存活时间。
4. unit
线程池中非核心线程保持存活的时间的单位
TimeUnit.DAYS; 天
TimeUnit.HOURS; 小时
TimeUnit.MINUTES; 分钟
TimeUnit.SECONDS; 秒
TimeUnit.MILLISECONDS; 毫秒
TimeUnit.MICROSECONDS; 微秒
TimeUnit.NANOSECONDS; 纳秒
5. workQueue
线程池等待队列,维护着等待执行的Runnable 对象。当运行当线程数=corePoolSize时,新的任务会被添加到workQueue 中,如果workQueue 也满了则尝试用非核心线程执行任务,等待队列应该尽量用有界的。
6. threadFactory
创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等。
7. handler
corePoolSize 、workQueue 、maximumPoolSize 都不可用的时候执行的饱和策略。